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"
14 #ifndef IFA_F_HOMEADDRESS
15 #define IFA_F_HOMEADDRESS 0x10
22 const int kTestInterfaceTun
= 123;
24 const char* TestGetInterfaceName(int interface_index
) {
25 if (interface_index
== kTestInterfaceTun
)
32 typedef std::vector
<char> Buffer
;
34 class AddressTrackerLinuxTest
: public testing::Test
{
36 AddressTrackerLinuxTest()
37 : tracker_(base::Bind(&base::DoNothing
),
38 base::Bind(&base::DoNothing
),
39 base::Bind(&base::DoNothing
)),
40 original_get_interface_name_(tracker_
.get_interface_name_
) {
41 tracker_
.get_interface_name_
= TestGetInterfaceName
;
44 bool HandleAddressMessage(const Buffer
& buf
) {
45 Buffer writable_buf
= buf
;
46 bool address_changed
= false;
47 bool link_changed
= false;
48 bool tunnel_changed
= false;
49 tracker_
.HandleMessage(&writable_buf
[0], buf
.size(),
50 &address_changed
, &link_changed
, &tunnel_changed
);
51 EXPECT_FALSE(link_changed
);
52 return address_changed
;
55 bool HandleLinkMessage(const Buffer
& buf
) {
56 Buffer writable_buf
= buf
;
57 bool address_changed
= false;
58 bool link_changed
= false;
59 bool tunnel_changed
= false;
60 tracker_
.HandleMessage(&writable_buf
[0], buf
.size(),
61 &address_changed
, &link_changed
, &tunnel_changed
);
62 EXPECT_FALSE(address_changed
);
66 bool HandleTunnelMessage(const Buffer
& buf
) {
67 Buffer writable_buf
= buf
;
68 bool address_changed
= false;
69 bool link_changed
= false;
70 bool tunnel_changed
= false;
71 tracker_
.HandleMessage(&writable_buf
[0], buf
.size(),
72 &address_changed
, &link_changed
, &tunnel_changed
);
73 EXPECT_FALSE(address_changed
);
74 return tunnel_changed
;
77 AddressTrackerLinux::AddressMap
GetAddressMap() {
78 return tracker_
.GetAddressMap();
81 const base::hash_set
<int>* GetOnlineLinks() const {
82 return &tracker_
.online_links_
;
85 AddressTrackerLinux tracker_
;
86 AddressTrackerLinux::GetInterfaceNameFunction original_get_interface_name_
;
91 class NetlinkMessage
{
93 explicit NetlinkMessage(uint16 type
) : buffer_(NLMSG_HDRLEN
) {
94 header()->nlmsg_type
= type
;
98 void AddPayload(const void* data
, size_t length
) {
99 CHECK_EQ(static_cast<size_t>(NLMSG_HDRLEN
),
100 buffer_
.size()) << "Payload must be added first";
101 Append(data
, length
);
105 void AddAttribute(uint16 type
, const void* data
, size_t length
) {
107 attr
.nla_len
= NLA_HDRLEN
+ length
;
108 attr
.nla_type
= type
;
109 Append(&attr
, sizeof(attr
));
111 Append(data
, length
);
115 void AppendTo(Buffer
* output
) const {
116 CHECK_EQ(NLMSG_ALIGN(output
->size()), output
->size());
117 output
->reserve(output
->size() + NLMSG_LENGTH(buffer_
.size()));
118 output
->insert(output
->end(), buffer_
.begin(), buffer_
.end());
122 void Append(const void* data
, size_t length
) {
123 const char* chardata
= reinterpret_cast<const char*>(data
);
124 buffer_
.insert(buffer_
.end(), chardata
, chardata
+ length
);
128 header()->nlmsg_len
= buffer_
.size();
129 buffer_
.insert(buffer_
.end(), NLMSG_ALIGN(buffer_
.size()) - buffer_
.size(),
131 CHECK(NLMSG_OK(header(), buffer_
.size()));
134 struct nlmsghdr
* header() {
135 return reinterpret_cast<struct nlmsghdr
*>(&buffer_
[0]);
141 #define INFINITY_LIFE_TIME 0xFFFFFFFF
143 void MakeAddrMessageWithCacheInfo(uint16 type
,
146 const IPAddressNumber
& address
,
147 const IPAddressNumber
& local
,
148 uint32 preferred_lifetime
,
150 NetlinkMessage
nlmsg(type
);
151 struct ifaddrmsg msg
= {};
152 msg
.ifa_family
= family
;
153 msg
.ifa_flags
= flags
;
154 nlmsg
.AddPayload(&msg
, sizeof(msg
));
156 nlmsg
.AddAttribute(IFA_ADDRESS
, &address
[0], address
.size());
158 nlmsg
.AddAttribute(IFA_LOCAL
, &local
[0], local
.size());
159 struct ifa_cacheinfo cache_info
= {};
160 cache_info
.ifa_prefered
= preferred_lifetime
;
161 cache_info
.ifa_valid
= INFINITY_LIFE_TIME
;
162 nlmsg
.AddAttribute(IFA_CACHEINFO
, &cache_info
, sizeof(cache_info
));
163 nlmsg
.AppendTo(output
);
166 void MakeAddrMessage(uint16 type
,
169 const IPAddressNumber
& address
,
170 const IPAddressNumber
& local
,
172 MakeAddrMessageWithCacheInfo(type
, flags
, family
, address
, local
,
173 INFINITY_LIFE_TIME
, output
);
176 void MakeLinkMessage(uint16 type
, uint32 flags
, uint32 index
, Buffer
* output
) {
177 NetlinkMessage
nlmsg(type
);
178 struct ifinfomsg msg
= {};
179 msg
.ifi_index
= index
;
180 msg
.ifi_flags
= flags
;
181 nlmsg
.AddPayload(&msg
, sizeof(msg
));
183 nlmsg
.AppendTo(output
);
186 const unsigned char kAddress0
[] = { 127, 0, 0, 1 };
187 const unsigned char kAddress1
[] = { 10, 0, 0, 1 };
188 const unsigned char kAddress2
[] = { 192, 168, 0, 1 };
189 const unsigned char kAddress3
[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
192 TEST_F(AddressTrackerLinuxTest
, NewAddress
) {
193 const IPAddressNumber kEmpty
;
194 const IPAddressNumber
kAddr0(kAddress0
, kAddress0
+ arraysize(kAddress0
));
195 const IPAddressNumber
kAddr1(kAddress1
, kAddress1
+ arraysize(kAddress1
));
196 const IPAddressNumber
kAddr2(kAddress2
, kAddress2
+ arraysize(kAddress2
));
197 const IPAddressNumber
kAddr3(kAddress3
, kAddress3
+ arraysize(kAddress3
));
200 MakeAddrMessage(RTM_NEWADDR
, IFA_F_TEMPORARY
, AF_INET
, kAddr0
, kEmpty
,
202 EXPECT_TRUE(HandleAddressMessage(buffer
));
203 AddressTrackerLinux::AddressMap map
= GetAddressMap();
204 EXPECT_EQ(1u, map
.size());
205 EXPECT_EQ(1u, map
.count(kAddr0
));
206 EXPECT_EQ(IFA_F_TEMPORARY
, map
[kAddr0
].ifa_flags
);
209 MakeAddrMessage(RTM_NEWADDR
, IFA_F_HOMEADDRESS
, AF_INET
, kAddr1
, kAddr2
,
211 EXPECT_TRUE(HandleAddressMessage(buffer
));
212 map
= GetAddressMap();
213 EXPECT_EQ(2u, map
.size());
214 EXPECT_EQ(1u, map
.count(kAddr0
));
215 EXPECT_EQ(1u, map
.count(kAddr2
));
216 EXPECT_EQ(IFA_F_HOMEADDRESS
, map
[kAddr2
].ifa_flags
);
219 MakeAddrMessage(RTM_NEWADDR
, 0, AF_INET6
, kEmpty
, kAddr3
, &buffer
);
220 EXPECT_TRUE(HandleAddressMessage(buffer
));
221 map
= GetAddressMap();
222 EXPECT_EQ(3u, map
.size());
223 EXPECT_EQ(1u, map
.count(kAddr3
));
226 TEST_F(AddressTrackerLinuxTest
, NewAddressChange
) {
227 const IPAddressNumber kEmpty
;
228 const IPAddressNumber
kAddr0(kAddress0
, kAddress0
+ arraysize(kAddress0
));
231 MakeAddrMessage(RTM_NEWADDR
, IFA_F_TEMPORARY
, AF_INET
, kAddr0
, kEmpty
,
233 EXPECT_TRUE(HandleAddressMessage(buffer
));
234 AddressTrackerLinux::AddressMap map
= GetAddressMap();
235 EXPECT_EQ(1u, map
.size());
236 EXPECT_EQ(1u, map
.count(kAddr0
));
237 EXPECT_EQ(IFA_F_TEMPORARY
, map
[kAddr0
].ifa_flags
);
240 MakeAddrMessage(RTM_NEWADDR
, IFA_F_HOMEADDRESS
, AF_INET
, kAddr0
, kEmpty
,
242 EXPECT_TRUE(HandleAddressMessage(buffer
));
243 map
= GetAddressMap();
244 EXPECT_EQ(1u, map
.size());
245 EXPECT_EQ(1u, map
.count(kAddr0
));
246 EXPECT_EQ(IFA_F_HOMEADDRESS
, map
[kAddr0
].ifa_flags
);
248 // Both messages in one buffer.
250 MakeAddrMessage(RTM_NEWADDR
, IFA_F_TEMPORARY
, AF_INET
, kAddr0
, kEmpty
,
252 MakeAddrMessage(RTM_NEWADDR
, IFA_F_HOMEADDRESS
, AF_INET
, kAddr0
, kEmpty
,
254 EXPECT_TRUE(HandleAddressMessage(buffer
));
255 map
= GetAddressMap();
256 EXPECT_EQ(1u, map
.size());
257 EXPECT_EQ(IFA_F_HOMEADDRESS
, map
[kAddr0
].ifa_flags
);
260 TEST_F(AddressTrackerLinuxTest
, NewAddressDuplicate
) {
261 const IPAddressNumber
kAddr0(kAddress0
, kAddress0
+ arraysize(kAddress0
));
264 MakeAddrMessage(RTM_NEWADDR
, IFA_F_TEMPORARY
, AF_INET
, kAddr0
, kAddr0
,
266 EXPECT_TRUE(HandleAddressMessage(buffer
));
267 AddressTrackerLinux::AddressMap map
= GetAddressMap();
268 EXPECT_EQ(1u, map
.size());
269 EXPECT_EQ(1u, map
.count(kAddr0
));
270 EXPECT_EQ(IFA_F_TEMPORARY
, map
[kAddr0
].ifa_flags
);
272 EXPECT_FALSE(HandleAddressMessage(buffer
));
273 map
= GetAddressMap();
274 EXPECT_EQ(1u, map
.size());
275 EXPECT_EQ(IFA_F_TEMPORARY
, map
[kAddr0
].ifa_flags
);
278 TEST_F(AddressTrackerLinuxTest
, DeleteAddress
) {
279 const IPAddressNumber kEmpty
;
280 const IPAddressNumber
kAddr0(kAddress0
, kAddress0
+ arraysize(kAddress0
));
281 const IPAddressNumber
kAddr1(kAddress1
, kAddress1
+ arraysize(kAddress1
));
282 const IPAddressNumber
kAddr2(kAddress2
, kAddress2
+ arraysize(kAddress2
));
285 MakeAddrMessage(RTM_NEWADDR
, 0, AF_INET
, kAddr0
, kEmpty
, &buffer
);
286 MakeAddrMessage(RTM_NEWADDR
, 0, AF_INET
, kAddr1
, kAddr2
, &buffer
);
287 EXPECT_TRUE(HandleAddressMessage(buffer
));
288 AddressTrackerLinux::AddressMap map
= GetAddressMap();
289 EXPECT_EQ(2u, map
.size());
292 MakeAddrMessage(RTM_DELADDR
, 0, AF_INET
, kEmpty
, kAddr0
, &buffer
);
293 EXPECT_TRUE(HandleAddressMessage(buffer
));
294 map
= GetAddressMap();
295 EXPECT_EQ(1u, map
.size());
296 EXPECT_EQ(0u, map
.count(kAddr0
));
297 EXPECT_EQ(1u, map
.count(kAddr2
));
300 MakeAddrMessage(RTM_DELADDR
, 0, AF_INET
, kAddr2
, kAddr1
, &buffer
);
301 // kAddr1 does not exist in the map.
302 EXPECT_FALSE(HandleAddressMessage(buffer
));
303 map
= GetAddressMap();
304 EXPECT_EQ(1u, map
.size());
307 MakeAddrMessage(RTM_DELADDR
, 0, AF_INET
, kAddr2
, kEmpty
, &buffer
);
308 EXPECT_TRUE(HandleAddressMessage(buffer
));
309 map
= GetAddressMap();
310 EXPECT_EQ(0u, map
.size());
313 TEST_F(AddressTrackerLinuxTest
, DeprecatedLifetime
) {
314 const IPAddressNumber kEmpty
;
315 const IPAddressNumber
kAddr3(kAddress3
, kAddress3
+ arraysize(kAddress3
));
318 MakeAddrMessage(RTM_NEWADDR
, 0, AF_INET6
, kEmpty
, kAddr3
, &buffer
);
319 EXPECT_TRUE(HandleAddressMessage(buffer
));
320 AddressTrackerLinux::AddressMap map
= GetAddressMap();
321 EXPECT_EQ(1u, map
.size());
322 EXPECT_EQ(1u, map
.count(kAddr3
));
323 EXPECT_EQ(0, map
[kAddr3
].ifa_flags
);
325 // Verify 0 preferred lifetime implies deprecated.
327 MakeAddrMessageWithCacheInfo(RTM_NEWADDR
, 0, AF_INET6
, kEmpty
, kAddr3
, 0,
329 EXPECT_TRUE(HandleAddressMessage(buffer
));
330 map
= GetAddressMap();
331 EXPECT_EQ(1u, map
.size());
332 EXPECT_EQ(IFA_F_DEPRECATED
, map
[kAddr3
].ifa_flags
);
334 // Verify properly flagged message doesn't imply change.
336 MakeAddrMessageWithCacheInfo(RTM_NEWADDR
, IFA_F_DEPRECATED
, AF_INET6
, kEmpty
,
338 EXPECT_FALSE(HandleAddressMessage(buffer
));
339 map
= GetAddressMap();
340 EXPECT_EQ(1u, map
.size());
341 EXPECT_EQ(IFA_F_DEPRECATED
, map
[kAddr3
].ifa_flags
);
343 // Verify implied deprecated doesn't imply change.
345 MakeAddrMessageWithCacheInfo(RTM_NEWADDR
, 0, AF_INET6
, kEmpty
, kAddr3
, 0,
347 EXPECT_FALSE(HandleAddressMessage(buffer
));
348 map
= GetAddressMap();
349 EXPECT_EQ(1u, map
.size());
350 EXPECT_EQ(IFA_F_DEPRECATED
, map
[kAddr3
].ifa_flags
);
353 TEST_F(AddressTrackerLinuxTest
, IgnoredMessage
) {
354 const IPAddressNumber kEmpty
;
355 const IPAddressNumber
kAddr0(kAddress0
, kAddress0
+ arraysize(kAddress0
));
356 const IPAddressNumber
kAddr3(kAddress3
, kAddress3
+ arraysize(kAddress3
));
360 MakeAddrMessage(RTM_NEWADDR
, 0, AF_UNSPEC
, kAddr3
, kAddr0
, &buffer
);
362 MakeAddrMessage(RTM_NEWADDR
, 0, AF_INET
, kEmpty
, kEmpty
, &buffer
);
364 MakeAddrMessage(RTM_DELROUTE
, 0, AF_INET6
, kAddr3
, kEmpty
, &buffer
);
365 EXPECT_FALSE(HandleAddressMessage(buffer
));
366 EXPECT_TRUE(GetAddressMap().empty());
368 // Valid message after ignored messages.
369 NetlinkMessage
nlmsg(RTM_NEWADDR
);
370 struct ifaddrmsg msg
= {};
371 msg
.ifa_family
= AF_INET
;
372 nlmsg
.AddPayload(&msg
, sizeof(msg
));
373 // Ignored attribute.
374 struct ifa_cacheinfo cache_info
= {};
375 nlmsg
.AddAttribute(IFA_CACHEINFO
, &cache_info
, sizeof(cache_info
));
376 nlmsg
.AddAttribute(IFA_ADDRESS
, &kAddr0
[0], kAddr0
.size());
377 nlmsg
.AppendTo(&buffer
);
379 EXPECT_TRUE(HandleAddressMessage(buffer
));
380 EXPECT_EQ(1u, GetAddressMap().size());
383 TEST_F(AddressTrackerLinuxTest
, AddInterface
) {
387 MakeLinkMessage(RTM_NEWLINK
,
388 IFF_LOOPBACK
| IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
,
390 EXPECT_FALSE(HandleLinkMessage(buffer
));
391 EXPECT_TRUE(GetOnlineLinks()->empty());
393 // Ignores not IFF_LOWER_UP.
394 MakeLinkMessage(RTM_NEWLINK
, IFF_UP
| IFF_RUNNING
, 0, &buffer
);
395 EXPECT_FALSE(HandleLinkMessage(buffer
));
396 EXPECT_TRUE(GetOnlineLinks()->empty());
399 MakeLinkMessage(RTM_DELLINK
, IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
, 0, &buffer
);
400 EXPECT_FALSE(HandleLinkMessage(buffer
));
401 EXPECT_TRUE(GetOnlineLinks()->empty());
404 MakeLinkMessage(RTM_NEWLINK
, IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
, 0, &buffer
);
405 EXPECT_TRUE(HandleLinkMessage(buffer
));
406 EXPECT_EQ(1u, GetOnlineLinks()->count(0));
407 EXPECT_EQ(1u, GetOnlineLinks()->size());
409 // Ignores redundant enables.
410 MakeLinkMessage(RTM_NEWLINK
, IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
, 0, &buffer
);
411 EXPECT_FALSE(HandleLinkMessage(buffer
));
412 EXPECT_EQ(1u, GetOnlineLinks()->count(0));
413 EXPECT_EQ(1u, GetOnlineLinks()->size());
415 // Verify adding another online device (e.g. VPN) is considered a change.
416 MakeLinkMessage(RTM_NEWLINK
, IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
, 1, &buffer
);
417 EXPECT_TRUE(HandleLinkMessage(buffer
));
418 EXPECT_EQ(1u, GetOnlineLinks()->count(0));
419 EXPECT_EQ(1u, GetOnlineLinks()->count(1));
420 EXPECT_EQ(2u, GetOnlineLinks()->size());
423 TEST_F(AddressTrackerLinuxTest
, RemoveInterface
) {
426 // Should disappear when not IFF_LOWER_UP.
427 MakeLinkMessage(RTM_NEWLINK
, IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
, 0, &buffer
);
428 EXPECT_TRUE(HandleLinkMessage(buffer
));
429 EXPECT_FALSE(GetOnlineLinks()->empty());
430 MakeLinkMessage(RTM_NEWLINK
, IFF_UP
| IFF_RUNNING
, 0, &buffer
);
431 EXPECT_TRUE(HandleLinkMessage(buffer
));
432 EXPECT_TRUE(GetOnlineLinks()->empty());
434 // Ignores redundant disables.
435 MakeLinkMessage(RTM_NEWLINK
, IFF_UP
| IFF_RUNNING
, 0, &buffer
);
436 EXPECT_FALSE(HandleLinkMessage(buffer
));
437 EXPECT_TRUE(GetOnlineLinks()->empty());
439 // Ignores deleting down interfaces.
440 MakeLinkMessage(RTM_DELLINK
, IFF_UP
| IFF_RUNNING
, 0, &buffer
);
441 EXPECT_FALSE(HandleLinkMessage(buffer
));
442 EXPECT_TRUE(GetOnlineLinks()->empty());
444 // Should disappear when deleted.
445 MakeLinkMessage(RTM_NEWLINK
, IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
, 0, &buffer
);
446 EXPECT_TRUE(HandleLinkMessage(buffer
));
447 EXPECT_FALSE(GetOnlineLinks()->empty());
448 MakeLinkMessage(RTM_DELLINK
, IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
, 0, &buffer
);
449 EXPECT_TRUE(HandleLinkMessage(buffer
));
450 EXPECT_TRUE(GetOnlineLinks()->empty());
453 TEST_F(AddressTrackerLinuxTest
, TunnelInterface
) {
456 // Ignores without "tun" prefixed name.
457 MakeLinkMessage(RTM_NEWLINK
,
458 IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
| IFF_POINTOPOINT
,
460 EXPECT_FALSE(HandleTunnelMessage(buffer
));
463 MakeLinkMessage(RTM_NEWLINK
,
464 IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
| IFF_POINTOPOINT
,
465 kTestInterfaceTun
, &buffer
);
466 EXPECT_TRUE(HandleTunnelMessage(buffer
));
468 // Ignores redundant enables.
469 MakeLinkMessage(RTM_NEWLINK
,
470 IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
| IFF_POINTOPOINT
,
471 kTestInterfaceTun
, &buffer
);
472 EXPECT_FALSE(HandleTunnelMessage(buffer
));
474 // Ignores deleting without "tun" prefixed name.
475 MakeLinkMessage(RTM_DELLINK
,
476 IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
| IFF_POINTOPOINT
,
478 EXPECT_FALSE(HandleTunnelMessage(buffer
));
480 // Verify successful deletion
481 MakeLinkMessage(RTM_DELLINK
,
482 IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
| IFF_POINTOPOINT
,
483 kTestInterfaceTun
, &buffer
);
484 EXPECT_TRUE(HandleTunnelMessage(buffer
));
486 // Ignores redundant deletions.
487 MakeLinkMessage(RTM_DELLINK
,
488 IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
| IFF_POINTOPOINT
,
489 kTestInterfaceTun
, &buffer
);
490 EXPECT_FALSE(HandleTunnelMessage(buffer
));
493 // Check AddressTrackerLinux::get_interface_name_ original implementation
494 // doesn't crash or return NULL.
495 TEST_F(AddressTrackerLinuxTest
, GetInterfaceName
) {
496 for (int i
= 0; i
< 10; i
++)
497 EXPECT_NE((const char*)NULL
, original_get_interface_name_(i
));
502 } // namespace internal