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. 4 5 #include "net/base/address_tracker_linux.h" 6 7 #include <linux/if.h> 8 9 #include <vector> 10 11 #include "base/bind.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 14 namespace net { 15 namespace internal { 16 17 typedef std::vector<char> Buffer; 18 19 void Noop() {} 20 21 class AddressTrackerLinuxTest : public testing::Test { 22 protected: 23 AddressTrackerLinuxTest() : tracker_(base::Bind(&Noop), base::Bind(&Noop)) {} 24 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; 32 } 33 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); 40 return link_changed; 41 } 42 43 AddressTrackerLinux::AddressMap GetAddressMap() { 44 return tracker_.GetAddressMap(); 45 } 46 47 const base::hash_set<int>* GetOnlineLinks() const { 48 return &tracker_.online_links_; 49 } 50 51 AddressTrackerLinux tracker_; 52 }; 53 54 namespace { 55 56 class NetlinkMessage { 57 public: 58 explicit NetlinkMessage(uint16 type) : buffer_(NLMSG_HDRLEN) { 59 header()->nlmsg_type = type; 60 Align(); 61 } 62 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"; 66 Append(data, length); 67 Align(); 68 } 69 70 void AddAttribute(uint16 type, const void* data, size_t length) { 71 struct nlattr attr; 72 attr.nla_len = NLA_HDRLEN + length; 73 attr.nla_type = type; 74 Append(&attr, sizeof(attr)); 75 Align(); 76 Append(data, length); 77 Align(); 78 } 79 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()); 84 } 85 86 private: 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); 90 } 91 92 void Align() { 93 header()->nlmsg_len = buffer_.size(); 94 buffer_.insert(buffer_.end(), NLMSG_ALIGN(buffer_.size()) - buffer_.size(), 95 0); 96 CHECK(NLMSG_OK(header(), buffer_.size())); 97 } 98 99 struct nlmsghdr* header() { 100 return reinterpret_cast<struct nlmsghdr*>(&buffer_[0]); 101 } 102 103 Buffer buffer_; 104 }; 105 106 void MakeAddrMessage(uint16 type, 107 uint8 flags, 108 uint8 family, 109 const IPAddressNumber& address, 110 const IPAddressNumber& local, 111 Buffer* output) { 112 NetlinkMessage nlmsg(type); 113 struct ifaddrmsg msg = {}; 114 msg.ifa_family = family; 115 msg.ifa_flags = flags; 116 nlmsg.AddPayload(&msg, sizeof(msg)); 117 if (address.size()) 118 nlmsg.AddAttribute(IFA_ADDRESS, &address[0], address.size()); 119 if (local.size()) 120 nlmsg.AddAttribute(IFA_LOCAL, &local[0], local.size()); 121 nlmsg.AppendTo(output); 122 } 123 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)); 130 output->clear(); 131 nlmsg.AppendTo(output); 132 } 133 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, 138 0, 0, 0, 1 }; 139 140 TEST_F(AddressTrackerLinuxTest, NewAddress) { 141 const IPAddressNumber kEmpty; 142 const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); 143 const IPAddressNumber kAddr1(kAddress1, kAddress1 + arraysize(kAddress1)); 144 const IPAddressNumber kAddr2(kAddress2, kAddress2 + arraysize(kAddress2)); 145 const IPAddressNumber kAddr3(kAddress3, kAddress3 + arraysize(kAddress3)); 146 147 Buffer buffer; 148 MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kEmpty, 149 &buffer); 150 EXPECT_TRUE(HandleAddressMessage(buffer)); 151 AddressTrackerLinux::AddressMap map = GetAddressMap(); 152 EXPECT_EQ(1u, map.size()); 153 EXPECT_EQ(1u, map.count(kAddr0)); 154 EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags); 155 156 buffer.clear(); 157 MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kAddr1, kAddr2, 158 &buffer); 159 EXPECT_TRUE(HandleAddressMessage(buffer)); 160 map = GetAddressMap(); 161 EXPECT_EQ(2u, map.size()); 162 EXPECT_EQ(1u, map.count(kAddr0)); 163 EXPECT_EQ(1u, map.count(kAddr2)); 164 EXPECT_EQ(IFA_F_HOMEADDRESS, map[kAddr2].ifa_flags); 165 166 buffer.clear(); 167 MakeAddrMessage(RTM_NEWADDR, 0, AF_INET6, kEmpty, kAddr3, &buffer); 168 EXPECT_TRUE(HandleAddressMessage(buffer)); 169 map = GetAddressMap(); 170 EXPECT_EQ(3u, map.size()); 171 EXPECT_EQ(1u, map.count(kAddr3)); 172 } 173 174 TEST_F(AddressTrackerLinuxTest, NewAddressChange) { 175 const IPAddressNumber kEmpty; 176 const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); 177 178 Buffer buffer; 179 MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kEmpty, 180 &buffer); 181 EXPECT_TRUE(HandleAddressMessage(buffer)); 182 AddressTrackerLinux::AddressMap map = GetAddressMap(); 183 EXPECT_EQ(1u, map.size()); 184 EXPECT_EQ(1u, map.count(kAddr0)); 185 EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags); 186 187 buffer.clear(); 188 MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kAddr0, kEmpty, 189 &buffer); 190 EXPECT_TRUE(HandleAddressMessage(buffer)); 191 map = GetAddressMap(); 192 EXPECT_EQ(1u, map.size()); 193 EXPECT_EQ(1u, map.count(kAddr0)); 194 EXPECT_EQ(IFA_F_HOMEADDRESS, map[kAddr0].ifa_flags); 195 196 // Both messages in one buffer. 197 buffer.clear(); 198 MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kEmpty, 199 &buffer); 200 MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kAddr0, kEmpty, 201 &buffer); 202 EXPECT_TRUE(HandleAddressMessage(buffer)); 203 map = GetAddressMap(); 204 EXPECT_EQ(1u, map.size()); 205 EXPECT_EQ(IFA_F_HOMEADDRESS, map[kAddr0].ifa_flags); 206 } 207 208 TEST_F(AddressTrackerLinuxTest, NewAddressDuplicate) { 209 const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); 210 211 Buffer buffer; 212 MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kAddr0, 213 &buffer); 214 EXPECT_TRUE(HandleAddressMessage(buffer)); 215 AddressTrackerLinux::AddressMap map = GetAddressMap(); 216 EXPECT_EQ(1u, map.size()); 217 EXPECT_EQ(1u, map.count(kAddr0)); 218 EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags); 219 220 EXPECT_FALSE(HandleAddressMessage(buffer)); 221 map = GetAddressMap(); 222 EXPECT_EQ(1u, map.size()); 223 EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags); 224 } 225 226 TEST_F(AddressTrackerLinuxTest, DeleteAddress) { 227 const IPAddressNumber kEmpty; 228 const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); 229 const IPAddressNumber kAddr1(kAddress1, kAddress1 + arraysize(kAddress1)); 230 const IPAddressNumber kAddr2(kAddress2, kAddress2 + arraysize(kAddress2)); 231 232 Buffer buffer; 233 MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kAddr0, kEmpty, &buffer); 234 MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kAddr1, kAddr2, &buffer); 235 EXPECT_TRUE(HandleAddressMessage(buffer)); 236 AddressTrackerLinux::AddressMap map = GetAddressMap(); 237 EXPECT_EQ(2u, map.size()); 238 239 buffer.clear(); 240 MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kEmpty, kAddr0, &buffer); 241 EXPECT_TRUE(HandleAddressMessage(buffer)); 242 map = GetAddressMap(); 243 EXPECT_EQ(1u, map.size()); 244 EXPECT_EQ(0u, map.count(kAddr0)); 245 EXPECT_EQ(1u, map.count(kAddr2)); 246 247 buffer.clear(); 248 MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kAddr2, kAddr1, &buffer); 249 // kAddr1 does not exist in the map. 250 EXPECT_FALSE(HandleAddressMessage(buffer)); 251 map = GetAddressMap(); 252 EXPECT_EQ(1u, map.size()); 253 254 buffer.clear(); 255 MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kAddr2, kEmpty, &buffer); 256 EXPECT_TRUE(HandleAddressMessage(buffer)); 257 map = GetAddressMap(); 258 EXPECT_EQ(0u, map.size()); 259 } 260 261 TEST_F(AddressTrackerLinuxTest, IgnoredMessage) { 262 const IPAddressNumber kEmpty; 263 const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); 264 const IPAddressNumber kAddr3(kAddress3, kAddress3 + arraysize(kAddress3)); 265 266 Buffer buffer; 267 // Ignored family. 268 MakeAddrMessage(RTM_NEWADDR, 0, AF_UNSPEC, kAddr3, kAddr0, &buffer); 269 // No address. 270 MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kEmpty, kEmpty, &buffer); 271 // Ignored type. 272 MakeAddrMessage(RTM_DELROUTE, 0, AF_INET6, kAddr3, kEmpty, &buffer); 273 EXPECT_FALSE(HandleAddressMessage(buffer)); 274 EXPECT_TRUE(GetAddressMap().empty()); 275 276 // Valid message after ignored messages. 277 NetlinkMessage nlmsg(RTM_NEWADDR); 278 struct ifaddrmsg msg = {}; 279 msg.ifa_family = AF_INET; 280 nlmsg.AddPayload(&msg, sizeof(msg)); 281 // Ignored attribute. 282 struct ifa_cacheinfo cache_info = {}; 283 nlmsg.AddAttribute(IFA_CACHEINFO, &cache_info, sizeof(cache_info)); 284 nlmsg.AddAttribute(IFA_ADDRESS, &kAddr0[0], kAddr0.size()); 285 nlmsg.AppendTo(&buffer); 286 287 EXPECT_TRUE(HandleAddressMessage(buffer)); 288 EXPECT_EQ(1u, GetAddressMap().size()); 289 } 290 291 TEST_F(AddressTrackerLinuxTest, AddInterface) { 292 Buffer buffer; 293 294 // Ignores loopback. 295 MakeLinkMessage(RTM_NEWLINK, 296 IFF_LOOPBACK | IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 297 0, &buffer); 298 EXPECT_FALSE(HandleLinkMessage(buffer)); 299 EXPECT_TRUE(GetOnlineLinks()->empty()); 300 301 // Ignores not IFF_LOWER_UP. 302 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, 0, &buffer); 303 EXPECT_FALSE(HandleLinkMessage(buffer)); 304 EXPECT_TRUE(GetOnlineLinks()->empty()); 305 306 // Ignores deletion. 307 MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); 308 EXPECT_FALSE(HandleLinkMessage(buffer)); 309 EXPECT_TRUE(GetOnlineLinks()->empty()); 310 311 // Verify success. 312 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); 313 EXPECT_TRUE(HandleLinkMessage(buffer)); 314 EXPECT_EQ(1u, GetOnlineLinks()->count(0)); 315 EXPECT_EQ(1u, GetOnlineLinks()->size()); 316 317 // Ignores redundant enables. 318 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); 319 EXPECT_FALSE(HandleLinkMessage(buffer)); 320 EXPECT_EQ(1u, GetOnlineLinks()->count(0)); 321 EXPECT_EQ(1u, GetOnlineLinks()->size()); 322 323 // Verify adding another online device (e.g. VPN) is considered a change. 324 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 1, &buffer); 325 EXPECT_TRUE(HandleLinkMessage(buffer)); 326 EXPECT_EQ(1u, GetOnlineLinks()->count(0)); 327 EXPECT_EQ(1u, GetOnlineLinks()->count(1)); 328 EXPECT_EQ(2u, GetOnlineLinks()->size()); 329 } 330 331 TEST_F(AddressTrackerLinuxTest, RemoveInterface) { 332 Buffer buffer; 333 334 // Should disappear when not IFF_LOWER_UP. 335 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); 336 EXPECT_TRUE(HandleLinkMessage(buffer)); 337 EXPECT_FALSE(GetOnlineLinks()->empty()); 338 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, 0, &buffer); 339 EXPECT_TRUE(HandleLinkMessage(buffer)); 340 EXPECT_TRUE(GetOnlineLinks()->empty()); 341 342 // Ignores redundant disables. 343 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, 0, &buffer); 344 EXPECT_FALSE(HandleLinkMessage(buffer)); 345 EXPECT_TRUE(GetOnlineLinks()->empty()); 346 347 // Ignores deleting down interfaces. 348 MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_RUNNING, 0, &buffer); 349 EXPECT_FALSE(HandleLinkMessage(buffer)); 350 EXPECT_TRUE(GetOnlineLinks()->empty()); 351 352 // Should disappear when deleted. 353 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); 354 EXPECT_TRUE(HandleLinkMessage(buffer)); 355 EXPECT_FALSE(GetOnlineLinks()->empty()); 356 MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); 357 EXPECT_TRUE(HandleLinkMessage(buffer)); 358 EXPECT_TRUE(GetOnlineLinks()->empty()); 359 } 360 361 } // namespace 362 363 } // namespace internal 364 } // namespace net 365