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 Buffer writable_buf = buf;
27 bool address_changed = false;
28 bool link_changed = false;
29 tracker_.HandleMessage(&writable_buf[0], buf.size(),
30 &address_changed, &link_changed);
31 EXPECT_FALSE(link_changed);
32 return address_changed;
35 bool HandleLinkMessage(const Buffer& buf) {
36 Buffer writable_buf = buf;
37 bool address_changed = false;
38 bool link_changed = false;
39 tracker_.HandleMessage(&writable_buf[0], buf.size(),
40 &address_changed, &link_changed);
41 EXPECT_FALSE(address_changed);
45 AddressTrackerLinux::AddressMap GetAddressMap() {
46 return tracker_.GetAddressMap();
49 const base::hash_set<int>* GetOnlineLinks() const {
50 return &tracker_.online_links_;
53 AddressTrackerLinux tracker_;
58 class NetlinkMessage {
60 explicit NetlinkMessage(uint16 type) : buffer_(NLMSG_HDRLEN) {
61 header()->nlmsg_type = type;
65 void AddPayload(const void* data, size_t length) {
66 CHECK_EQ(static_cast<size_t>(NLMSG_HDRLEN),
67 buffer_.size()) << "Payload must be added first";
72 void AddAttribute(uint16 type, const void* data, size_t length) {
74 attr.nla_len = NLA_HDRLEN + length;
76 Append(&attr, sizeof(attr));
82 void AppendTo(Buffer* output) const {
83 CHECK_EQ(NLMSG_ALIGN(output->size()), output->size());
84 output->reserve(output->size() + NLMSG_LENGTH(buffer_.size()));
85 output->insert(output->end(), buffer_.begin(), buffer_.end());
89 void Append(const void* data, size_t length) {
90 const char* chardata = reinterpret_cast<const char*>(data);
91 buffer_.insert(buffer_.end(), chardata, chardata + length);
95 header()->nlmsg_len = buffer_.size();
96 buffer_.insert(buffer_.end(), NLMSG_ALIGN(buffer_.size()) - buffer_.size(),
98 CHECK(NLMSG_OK(header(), buffer_.size()));
101 struct nlmsghdr* header() {
102 return reinterpret_cast<struct nlmsghdr*>(&buffer_[0]);
108 #define INFINITY_LIFE_TIME 0xFFFFFFFF
110 void MakeAddrMessageWithCacheInfo(uint16 type,
113 const IPAddressNumber& address,
114 const IPAddressNumber& local,
115 uint32 preferred_lifetime,
117 NetlinkMessage nlmsg(type);
118 struct ifaddrmsg msg = {};
119 msg.ifa_family = family;
120 msg.ifa_flags = flags;
121 nlmsg.AddPayload(&msg, sizeof(msg));
123 nlmsg.AddAttribute(IFA_ADDRESS, &address[0], address.size());
125 nlmsg.AddAttribute(IFA_LOCAL, &local[0], local.size());
126 struct ifa_cacheinfo cache_info = {};
127 cache_info.ifa_prefered = preferred_lifetime;
128 cache_info.ifa_valid = INFINITY_LIFE_TIME;
129 nlmsg.AddAttribute(IFA_CACHEINFO, &cache_info, sizeof(cache_info));
130 nlmsg.AppendTo(output);
133 void MakeAddrMessage(uint16 type,
136 const IPAddressNumber& address,
137 const IPAddressNumber& local,
139 MakeAddrMessageWithCacheInfo(type, flags, family, address, local,
140 INFINITY_LIFE_TIME, output);
143 void MakeLinkMessage(uint16 type, uint32 flags, uint32 index, Buffer* output) {
144 NetlinkMessage nlmsg(type);
145 struct ifinfomsg msg = {};
146 msg.ifi_index = index;
147 msg.ifi_flags = flags;
148 nlmsg.AddPayload(&msg, sizeof(msg));
150 nlmsg.AppendTo(output);
153 const unsigned char kAddress0[] = { 127, 0, 0, 1 };
154 const unsigned char kAddress1[] = { 10, 0, 0, 1 };
155 const unsigned char kAddress2[] = { 192, 168, 0, 1 };
156 const unsigned char kAddress3[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
159 TEST_F(AddressTrackerLinuxTest, NewAddress) {
160 const IPAddressNumber kEmpty;
161 const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0));
162 const IPAddressNumber kAddr1(kAddress1, kAddress1 + arraysize(kAddress1));
163 const IPAddressNumber kAddr2(kAddress2, kAddress2 + arraysize(kAddress2));
164 const IPAddressNumber kAddr3(kAddress3, kAddress3 + arraysize(kAddress3));
167 MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kEmpty,
169 EXPECT_TRUE(HandleAddressMessage(buffer));
170 AddressTrackerLinux::AddressMap map = GetAddressMap();
171 EXPECT_EQ(1u, map.size());
172 EXPECT_EQ(1u, map.count(kAddr0));
173 EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags);
176 MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kAddr1, kAddr2,
178 EXPECT_TRUE(HandleAddressMessage(buffer));
179 map = GetAddressMap();
180 EXPECT_EQ(2u, map.size());
181 EXPECT_EQ(1u, map.count(kAddr0));
182 EXPECT_EQ(1u, map.count(kAddr2));
183 EXPECT_EQ(IFA_F_HOMEADDRESS, map[kAddr2].ifa_flags);
186 MakeAddrMessage(RTM_NEWADDR, 0, AF_INET6, kEmpty, kAddr3, &buffer);
187 EXPECT_TRUE(HandleAddressMessage(buffer));
188 map = GetAddressMap();
189 EXPECT_EQ(3u, map.size());
190 EXPECT_EQ(1u, map.count(kAddr3));
193 TEST_F(AddressTrackerLinuxTest, NewAddressChange) {
194 const IPAddressNumber kEmpty;
195 const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0));
198 MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kEmpty,
200 EXPECT_TRUE(HandleAddressMessage(buffer));
201 AddressTrackerLinux::AddressMap map = GetAddressMap();
202 EXPECT_EQ(1u, map.size());
203 EXPECT_EQ(1u, map.count(kAddr0));
204 EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags);
207 MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kAddr0, kEmpty,
209 EXPECT_TRUE(HandleAddressMessage(buffer));
210 map = GetAddressMap();
211 EXPECT_EQ(1u, map.size());
212 EXPECT_EQ(1u, map.count(kAddr0));
213 EXPECT_EQ(IFA_F_HOMEADDRESS, map[kAddr0].ifa_flags);
215 // Both messages in one buffer.
217 MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kEmpty,
219 MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kAddr0, kEmpty,
221 EXPECT_TRUE(HandleAddressMessage(buffer));
222 map = GetAddressMap();
223 EXPECT_EQ(1u, map.size());
224 EXPECT_EQ(IFA_F_HOMEADDRESS, map[kAddr0].ifa_flags);
227 TEST_F(AddressTrackerLinuxTest, NewAddressDuplicate) {
228 const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0));
231 MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kAddr0,
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);
239 EXPECT_FALSE(HandleAddressMessage(buffer));
240 map = GetAddressMap();
241 EXPECT_EQ(1u, map.size());
242 EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags);
245 TEST_F(AddressTrackerLinuxTest, DeleteAddress) {
246 const IPAddressNumber kEmpty;
247 const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0));
248 const IPAddressNumber kAddr1(kAddress1, kAddress1 + arraysize(kAddress1));
249 const IPAddressNumber kAddr2(kAddress2, kAddress2 + arraysize(kAddress2));
252 MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kAddr0, kEmpty, &buffer);
253 MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kAddr1, kAddr2, &buffer);
254 EXPECT_TRUE(HandleAddressMessage(buffer));
255 AddressTrackerLinux::AddressMap map = GetAddressMap();
256 EXPECT_EQ(2u, map.size());
259 MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kEmpty, kAddr0, &buffer);
260 EXPECT_TRUE(HandleAddressMessage(buffer));
261 map = GetAddressMap();
262 EXPECT_EQ(1u, map.size());
263 EXPECT_EQ(0u, map.count(kAddr0));
264 EXPECT_EQ(1u, map.count(kAddr2));
267 MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kAddr2, kAddr1, &buffer);
268 // kAddr1 does not exist in the map.
269 EXPECT_FALSE(HandleAddressMessage(buffer));
270 map = GetAddressMap();
271 EXPECT_EQ(1u, map.size());
274 MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kAddr2, kEmpty, &buffer);
275 EXPECT_TRUE(HandleAddressMessage(buffer));
276 map = GetAddressMap();
277 EXPECT_EQ(0u, map.size());
280 TEST_F(AddressTrackerLinuxTest, DeprecatedLifetime) {
281 const IPAddressNumber kEmpty;
282 const IPAddressNumber kAddr3(kAddress3, kAddress3 + arraysize(kAddress3));
285 MakeAddrMessage(RTM_NEWADDR, 0, AF_INET6, kEmpty, kAddr3, &buffer);
286 EXPECT_TRUE(HandleAddressMessage(buffer));
287 AddressTrackerLinux::AddressMap map = GetAddressMap();
288 EXPECT_EQ(1u, map.size());
289 EXPECT_EQ(1u, map.count(kAddr3));
290 EXPECT_EQ(0, map[kAddr3].ifa_flags);
292 // Verify 0 preferred lifetime implies deprecated.
294 MakeAddrMessageWithCacheInfo(RTM_NEWADDR, 0, AF_INET6, kEmpty, kAddr3, 0,
296 EXPECT_TRUE(HandleAddressMessage(buffer));
297 map = GetAddressMap();
298 EXPECT_EQ(1u, map.size());
299 EXPECT_EQ(IFA_F_DEPRECATED, map[kAddr3].ifa_flags);
301 // Verify properly flagged message doesn't imply change.
303 MakeAddrMessageWithCacheInfo(RTM_NEWADDR, IFA_F_DEPRECATED, AF_INET6, kEmpty,
305 EXPECT_FALSE(HandleAddressMessage(buffer));
306 map = GetAddressMap();
307 EXPECT_EQ(1u, map.size());
308 EXPECT_EQ(IFA_F_DEPRECATED, map[kAddr3].ifa_flags);
310 // Verify implied deprecated doesn't imply change.
312 MakeAddrMessageWithCacheInfo(RTM_NEWADDR, 0, AF_INET6, kEmpty, kAddr3, 0,
314 EXPECT_FALSE(HandleAddressMessage(buffer));
315 map = GetAddressMap();
316 EXPECT_EQ(1u, map.size());
317 EXPECT_EQ(IFA_F_DEPRECATED, map[kAddr3].ifa_flags);
320 TEST_F(AddressTrackerLinuxTest, IgnoredMessage) {
321 const IPAddressNumber kEmpty;
322 const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0));
323 const IPAddressNumber kAddr3(kAddress3, kAddress3 + arraysize(kAddress3));
327 MakeAddrMessage(RTM_NEWADDR, 0, AF_UNSPEC, kAddr3, kAddr0, &buffer);
329 MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kEmpty, kEmpty, &buffer);
331 MakeAddrMessage(RTM_DELROUTE, 0, AF_INET6, kAddr3, kEmpty, &buffer);
332 EXPECT_FALSE(HandleAddressMessage(buffer));
333 EXPECT_TRUE(GetAddressMap().empty());
335 // Valid message after ignored messages.
336 NetlinkMessage nlmsg(RTM_NEWADDR);
337 struct ifaddrmsg msg = {};
338 msg.ifa_family = AF_INET;
339 nlmsg.AddPayload(&msg, sizeof(msg));
340 // Ignored attribute.
341 struct ifa_cacheinfo cache_info = {};
342 nlmsg.AddAttribute(IFA_CACHEINFO, &cache_info, sizeof(cache_info));
343 nlmsg.AddAttribute(IFA_ADDRESS, &kAddr0[0], kAddr0.size());
344 nlmsg.AppendTo(&buffer);
346 EXPECT_TRUE(HandleAddressMessage(buffer));
347 EXPECT_EQ(1u, GetAddressMap().size());
350 TEST_F(AddressTrackerLinuxTest, AddInterface) {
354 MakeLinkMessage(RTM_NEWLINK,
355 IFF_LOOPBACK | IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
357 EXPECT_FALSE(HandleLinkMessage(buffer));
358 EXPECT_TRUE(GetOnlineLinks()->empty());
360 // Ignores not IFF_LOWER_UP.
361 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, 0, &buffer);
362 EXPECT_FALSE(HandleLinkMessage(buffer));
363 EXPECT_TRUE(GetOnlineLinks()->empty());
366 MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer);
367 EXPECT_FALSE(HandleLinkMessage(buffer));
368 EXPECT_TRUE(GetOnlineLinks()->empty());
371 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer);
372 EXPECT_TRUE(HandleLinkMessage(buffer));
373 EXPECT_EQ(1u, GetOnlineLinks()->count(0));
374 EXPECT_EQ(1u, GetOnlineLinks()->size());
376 // Ignores redundant enables.
377 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer);
378 EXPECT_FALSE(HandleLinkMessage(buffer));
379 EXPECT_EQ(1u, GetOnlineLinks()->count(0));
380 EXPECT_EQ(1u, GetOnlineLinks()->size());
382 // Verify adding another online device (e.g. VPN) is considered a change.
383 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 1, &buffer);
384 EXPECT_TRUE(HandleLinkMessage(buffer));
385 EXPECT_EQ(1u, GetOnlineLinks()->count(0));
386 EXPECT_EQ(1u, GetOnlineLinks()->count(1));
387 EXPECT_EQ(2u, GetOnlineLinks()->size());
390 TEST_F(AddressTrackerLinuxTest, RemoveInterface) {
393 // Should disappear when not IFF_LOWER_UP.
394 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer);
395 EXPECT_TRUE(HandleLinkMessage(buffer));
396 EXPECT_FALSE(GetOnlineLinks()->empty());
397 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, 0, &buffer);
398 EXPECT_TRUE(HandleLinkMessage(buffer));
399 EXPECT_TRUE(GetOnlineLinks()->empty());
401 // Ignores redundant disables.
402 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, 0, &buffer);
403 EXPECT_FALSE(HandleLinkMessage(buffer));
404 EXPECT_TRUE(GetOnlineLinks()->empty());
406 // Ignores deleting down interfaces.
407 MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_RUNNING, 0, &buffer);
408 EXPECT_FALSE(HandleLinkMessage(buffer));
409 EXPECT_TRUE(GetOnlineLinks()->empty());
411 // Should disappear when deleted.
412 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer);
413 EXPECT_TRUE(HandleLinkMessage(buffer));
414 EXPECT_FALSE(GetOnlineLinks()->empty());
415 MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer);
416 EXPECT_TRUE(HandleLinkMessage(buffer));
417 EXPECT_TRUE(GetOnlineLinks()->empty());
422 } // namespace internal