Home | History | Annotate | Download | only in base
      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