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 const unsigned char kAddress4[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 140 169, 254, 0, 1 }; 141 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)); 148 149 Buffer buffer; 150 MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kEmpty, 151 &buffer); 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); 157 158 buffer.clear(); 159 MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kAddr1, kAddr2, 160 &buffer); 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); 167 168 buffer.clear(); 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)); 174 } 175 176 TEST_F(AddressTrackerLinuxTest, NewAddressChange) { 177 const IPAddressNumber kEmpty; 178 const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); 179 180 Buffer buffer; 181 MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kEmpty, 182 &buffer); 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); 188 189 buffer.clear(); 190 MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kAddr0, kEmpty, 191 &buffer); 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); 197 198 // Both messages in one buffer. 199 buffer.clear(); 200 MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kEmpty, 201 &buffer); 202 MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kAddr0, kEmpty, 203 &buffer); 204 EXPECT_TRUE(HandleAddressMessage(buffer)); 205 map = GetAddressMap(); 206 EXPECT_EQ(1u, map.size()); 207 EXPECT_EQ(IFA_F_HOMEADDRESS, map[kAddr0].ifa_flags); 208 } 209 210 TEST_F(AddressTrackerLinuxTest, NewAddressDuplicate) { 211 const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); 212 213 Buffer buffer; 214 MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kAddr0, 215 &buffer); 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); 221 222 EXPECT_FALSE(HandleAddressMessage(buffer)); 223 map = GetAddressMap(); 224 EXPECT_EQ(1u, map.size()); 225 EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags); 226 } 227 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)); 233 234 Buffer buffer; 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()); 240 241 buffer.clear(); 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)); 248 249 buffer.clear(); 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()); 255 256 buffer.clear(); 257 MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kAddr2, kEmpty, &buffer); 258 EXPECT_TRUE(HandleAddressMessage(buffer)); 259 map = GetAddressMap(); 260 EXPECT_EQ(0u, map.size()); 261 } 262 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)); 267 268 Buffer buffer; 269 // Ignored family. 270 MakeAddrMessage(RTM_NEWADDR, 0, AF_UNSPEC, kAddr3, kAddr0, &buffer); 271 // No address. 272 MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kEmpty, kEmpty, &buffer); 273 // Ignored type. 274 MakeAddrMessage(RTM_DELROUTE, 0, AF_INET6, kAddr3, kEmpty, &buffer); 275 EXPECT_FALSE(HandleAddressMessage(buffer)); 276 EXPECT_TRUE(GetAddressMap().empty()); 277 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); 288 289 EXPECT_TRUE(HandleAddressMessage(buffer)); 290 EXPECT_EQ(1u, GetAddressMap().size()); 291 } 292 293 TEST_F(AddressTrackerLinuxTest, AddInterface) { 294 Buffer buffer; 295 296 // Ignores loopback. 297 MakeLinkMessage(RTM_NEWLINK, 298 IFF_LOOPBACK | IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 299 0, &buffer); 300 EXPECT_FALSE(HandleLinkMessage(buffer)); 301 EXPECT_TRUE(GetOnlineLinks()->empty()); 302 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()); 307 308 // Ignores deletion. 309 MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); 310 EXPECT_FALSE(HandleLinkMessage(buffer)); 311 EXPECT_TRUE(GetOnlineLinks()->empty()); 312 313 // Verify success. 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()); 318 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()); 324 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()); 331 } 332 333 TEST_F(AddressTrackerLinuxTest, RemoveInterface) { 334 Buffer buffer; 335 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()); 343 344 // Ignores redundant disables. 345 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, 0, &buffer); 346 EXPECT_FALSE(HandleLinkMessage(buffer)); 347 EXPECT_TRUE(GetOnlineLinks()->empty()); 348 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()); 353 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()); 361 } 362 363 } // namespace 364 365 } // namespace internal 366 } // namespace net 367