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 
    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