Home | History | Annotate | Download | only in shill
      1 //
      2 // Copyright (C) 2012 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #include "shill/routing_table.h"
     18 
     19 #include <linux/rtnetlink.h>
     20 #include <sys/socket.h>
     21 
     22 #include <memory>
     23 #include <vector>
     24 
     25 #include <base/bind.h>
     26 #include <base/callback.h>
     27 #include <base/memory/weak_ptr.h>
     28 #include <base/stl_util.h>
     29 #include <gtest/gtest.h>
     30 #include <gmock/gmock.h>
     31 
     32 #include "shill/event_dispatcher.h"
     33 #include "shill/ipconfig.h"
     34 #include "shill/logging.h"
     35 #include "shill/mock_control.h"
     36 #include "shill/net/byte_string.h"
     37 #include "shill/net/mock_rtnl_handler.h"
     38 #include "shill/net/rtnl_message.h"
     39 #include "shill/routing_table_entry.h"
     40 
     41 using base::Bind;
     42 using base::Callback;
     43 using base::Unretained;
     44 using std::deque;
     45 using std::vector;
     46 using testing::_;
     47 using testing::Field;
     48 using testing::Invoke;
     49 using testing::Return;
     50 using testing::StrictMock;
     51 using testing::Test;
     52 
     53 namespace shill {
     54 
     55 class TestEventDispatcher : public EventDispatcher {
     56  public:
     57   virtual IOHandler* CreateInputHandler(
     58       int /*fd*/,
     59       const IOHandler::InputCallback& /*input_callback*/,
     60       const IOHandler::ErrorCallback& /*error_callback*/) {
     61     return nullptr;
     62   }
     63 };
     64 
     65 class RoutingTableTest : public Test {
     66  public:
     67   static const uint8_t kTestTableId;
     68 
     69   RoutingTableTest() : routing_table_(new RoutingTable()) {}
     70 
     71   virtual void SetUp() {
     72     routing_table_->rtnl_handler_ = &rtnl_handler_;
     73     ON_CALL(rtnl_handler_, SendMessage(_)).WillByDefault(Return(true));
     74   }
     75 
     76   virtual void TearDown() {
     77     RTNLHandler::GetInstance()->Stop();
     78   }
     79 
     80   std::unordered_map<int, vector<RoutingTableEntry>>* GetRoutingTables() {
     81     return &routing_table_->tables_;
     82   }
     83 
     84   deque<RoutingTable::Query>* GetQueries() {
     85     return &routing_table_->route_queries_;
     86   }
     87 
     88   void SendRouteEntry(RTNLMessage::Mode mode,
     89                       uint32_t interface_index,
     90                       const RoutingTableEntry& entry);
     91 
     92   void SendRouteEntryWithSeqAndProto(RTNLMessage::Mode mode,
     93                                      uint32_t interface_index,
     94                                      const RoutingTableEntry& entry,
     95                                      uint32_t seq,
     96                                      unsigned char proto);
     97 
     98   void SendRouteMessage(const RTNLMessage& msg);
     99 
    100   bool SetSequenceForMessage(RTNLMessage* message) {
    101     message->set_seq(RoutingTableTest::kTestRequestSeq);
    102     return true;
    103   }
    104 
    105  protected:
    106   static const uint32_t kTestDeviceIndex0;
    107   static const uint32_t kTestDeviceIndex1;
    108   static const char kTestDeviceName0[];
    109   static const char kTestDeviceNetAddress4[];
    110   static const char kTestForeignNetAddress4[];
    111   static const char kTestForeignNetGateway4[];
    112   static const char kTestForeignNetAddress6[];
    113   static const char kTestForeignNetGateway6[];
    114   static const char kTestGatewayAddress4[];
    115   static const char kTestNetAddress0[];
    116   static const char kTestNetAddress1[];
    117   static const char kTestRemoteAddress4[];
    118   static const char kTestRemoteNetmask4[];
    119   static const char kTestRemoteNetwork4[];
    120   static const int kTestRemotePrefix4;
    121   static const uint32_t kTestRequestSeq;
    122   static const int kTestRouteTag;
    123 
    124   class QueryCallbackTarget {
    125    public:
    126     QueryCallbackTarget()
    127         : weak_ptr_factory_(this),
    128           mocked_callback_(
    129               Bind(&QueryCallbackTarget::MockedTarget, Unretained(this))),
    130           unreached_callback_(Bind(&QueryCallbackTarget::UnreachedTarget,
    131                                    weak_ptr_factory_.GetWeakPtr())) {}
    132 
    133     MOCK_METHOD2(MockedTarget,
    134                  void(int interface_index, const RoutingTableEntry& entry));
    135 
    136     void UnreachedTarget(int interface_index, const RoutingTableEntry& entry) {
    137       CHECK(false);
    138     }
    139 
    140     const RoutingTable::Query::Callback& mocked_callback() const {
    141       return mocked_callback_;
    142     }
    143 
    144     const RoutingTable::Query::Callback& unreached_callback() const {
    145       return unreached_callback_;
    146     }
    147 
    148    private:
    149     base::WeakPtrFactory<QueryCallbackTarget> weak_ptr_factory_;
    150     const RoutingTable::Query::Callback mocked_callback_;
    151     const RoutingTable::Query::Callback unreached_callback_;
    152   };
    153 
    154   std::unique_ptr<RoutingTable> routing_table_;
    155   TestEventDispatcher dispatcher_;
    156   StrictMock<MockRTNLHandler> rtnl_handler_;
    157 };
    158 
    159 const uint32_t RoutingTableTest::kTestDeviceIndex0 = 12345;
    160 const uint32_t RoutingTableTest::kTestDeviceIndex1 = 67890;
    161 const char RoutingTableTest::kTestDeviceName0[] = "test-device0";
    162 const char RoutingTableTest::kTestDeviceNetAddress4[] = "192.168.2.0/24";
    163 const char RoutingTableTest::kTestForeignNetAddress4[] = "192.168.2.2";
    164 const char RoutingTableTest::kTestForeignNetGateway4[] = "192.168.2.1";
    165 const char RoutingTableTest::kTestForeignNetAddress6[] = "2000::/3";
    166 const char RoutingTableTest::kTestForeignNetGateway6[] = "fe80:::::1";
    167 const char RoutingTableTest::kTestGatewayAddress4[] = "192.168.2.254";
    168 const char RoutingTableTest::kTestNetAddress0[] = "192.168.1.1";
    169 const char RoutingTableTest::kTestNetAddress1[] = "192.168.1.2";
    170 const char RoutingTableTest::kTestRemoteAddress4[] = "192.168.2.254";
    171 const char RoutingTableTest::kTestRemoteNetmask4[] = "255.255.255.0";
    172 const char RoutingTableTest::kTestRemoteNetwork4[] = "192.168.100.0";
    173 const int RoutingTableTest::kTestRemotePrefix4 = 24;
    174 const uint32_t RoutingTableTest::kTestRequestSeq = 456;
    175 const int RoutingTableTest::kTestRouteTag = 789;
    176 const uint8_t RoutingTableTest::kTestTableId = 0xa5;
    177 
    178 namespace {
    179 
    180 MATCHER_P3(IsBlackholeRoutingPacket, index, family, metric, "") {
    181   const RTNLMessage::RouteStatus& status = arg->route_status();
    182 
    183   uint32_t oif;
    184   uint32_t priority;
    185 
    186   return
    187       arg->type() == RTNLMessage::kTypeRoute &&
    188       arg->family() == family &&
    189       arg->flags() == (NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL) &&
    190       status.table == RoutingTableTest::kTestTableId &&
    191       status.protocol == RTPROT_BOOT &&
    192       status.scope == RT_SCOPE_UNIVERSE &&
    193       status.type == RTN_BLACKHOLE &&
    194       !arg->HasAttribute(RTA_DST) &&
    195       !arg->HasAttribute(RTA_SRC) &&
    196       !arg->HasAttribute(RTA_GATEWAY) &&
    197       arg->GetAttribute(RTA_OIF).ConvertToCPUUInt32(&oif) &&
    198       oif == index &&
    199       arg->GetAttribute(RTA_PRIORITY).ConvertToCPUUInt32(&priority) &&
    200       priority == metric;
    201 }
    202 
    203 MATCHER_P4(IsRoutingPacket, mode, index, entry, flags, "") {
    204   const RTNLMessage::RouteStatus& status = arg->route_status();
    205 
    206   uint32_t oif;
    207   uint32_t priority;
    208 
    209   return
    210       arg->type() == RTNLMessage::kTypeRoute &&
    211       arg->family() == entry.gateway.family() &&
    212       arg->flags() == (NLM_F_REQUEST | flags) &&
    213       status.table == RoutingTableTest::kTestTableId &&
    214       entry.table == RoutingTableTest::kTestTableId &&
    215       status.protocol == RTPROT_BOOT &&
    216       status.scope == entry.scope &&
    217       status.type == RTN_UNICAST &&
    218       arg->HasAttribute(RTA_DST) &&
    219       IPAddress(arg->family(),
    220                 arg->GetAttribute(RTA_DST),
    221                 status.dst_prefix).Equals(entry.dst) &&
    222       ((!arg->HasAttribute(RTA_SRC) && entry.src.IsDefault()) ||
    223        (arg->HasAttribute(RTA_SRC) && IPAddress(arg->family(),
    224                  arg->GetAttribute(RTA_SRC),
    225                  status.src_prefix).Equals(entry.src))) &&
    226       ((!arg->HasAttribute(RTA_GATEWAY) && entry.gateway.IsDefault()) ||
    227        (arg->HasAttribute(RTA_GATEWAY) && IPAddress(arg->family(),
    228                 arg->GetAttribute(RTA_GATEWAY)).Equals(entry.gateway))) &&
    229       arg->GetAttribute(RTA_OIF).ConvertToCPUUInt32(&oif) &&
    230       oif == index &&
    231       arg->GetAttribute(RTA_PRIORITY).ConvertToCPUUInt32(&priority) &&
    232       priority == entry.metric;
    233 }
    234 
    235 }  // namespace
    236 
    237 void RoutingTableTest::SendRouteEntry(RTNLMessage::Mode mode,
    238                                       uint32_t interface_index,
    239                                       const RoutingTableEntry& entry) {
    240   SendRouteEntryWithSeqAndProto(mode, interface_index, entry, 0, RTPROT_BOOT);
    241 }
    242 
    243 void RoutingTableTest::SendRouteEntryWithSeqAndProto(
    244     RTNLMessage::Mode mode,
    245     uint32_t interface_index,
    246     const RoutingTableEntry& entry,
    247     uint32_t seq,
    248     unsigned char proto) {
    249   RTNLMessage msg(
    250       RTNLMessage::kTypeRoute,
    251       mode,
    252       0,
    253       seq,
    254       0,
    255       0,
    256       entry.dst.family());
    257 
    258   msg.set_route_status(RTNLMessage::RouteStatus(
    259       entry.dst.prefix(),
    260       entry.src.prefix(),
    261       entry.table,
    262       proto,
    263       entry.scope,
    264       RTN_UNICAST,
    265       0));
    266 
    267   msg.SetAttribute(RTA_DST, entry.dst.address());
    268   if (!entry.src.IsDefault()) {
    269     msg.SetAttribute(RTA_SRC, entry.src.address());
    270   }
    271   if (!entry.gateway.IsDefault()) {
    272     msg.SetAttribute(RTA_GATEWAY, entry.gateway.address());
    273   }
    274   msg.SetAttribute(RTA_PRIORITY, ByteString::CreateFromCPUUInt32(entry.metric));
    275   msg.SetAttribute(RTA_OIF, ByteString::CreateFromCPUUInt32(interface_index));
    276 
    277   routing_table_->RouteMsgHandler(msg);
    278 }
    279 
    280 void RoutingTableTest::SendRouteMessage(const RTNLMessage& msg) {
    281   routing_table_->RouteMsgHandler(msg);
    282 }
    283 
    284 TEST_F(RoutingTableTest, Start) {
    285   EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestRoute));
    286   routing_table_->Start();
    287 }
    288 
    289 TEST_F(RoutingTableTest, RouteAddDelete) {
    290   // Expect the tables to be empty by default.
    291   EXPECT_EQ(0, GetRoutingTables()->size());
    292 
    293   IPAddress default_address(IPAddress::kFamilyIPv4);
    294   default_address.SetAddressToDefault();
    295 
    296   IPAddress gateway_address0(IPAddress::kFamilyIPv4);
    297   gateway_address0.SetAddressFromString(kTestNetAddress0);
    298 
    299   int metric = 10;
    300 
    301   RoutingTableEntry entry0(default_address,
    302                            default_address,
    303                            gateway_address0,
    304                            metric,
    305                            RT_SCOPE_UNIVERSE,
    306                            true,
    307                            kTestTableId,
    308                            RoutingTableEntry::kDefaultTag);
    309   // Add a single entry.
    310   SendRouteEntry(RTNLMessage::kModeAdd,
    311                  kTestDeviceIndex0,
    312                  entry0);
    313 
    314   std::unordered_map<int, vector<RoutingTableEntry>>* tables =
    315       GetRoutingTables();
    316 
    317   // We should have a single table, which should in turn have a single entry.
    318   EXPECT_EQ(1, tables->size());
    319   EXPECT_TRUE(ContainsKey(*tables, kTestDeviceIndex0));
    320   EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
    321 
    322   RoutingTableEntry test_entry = (*tables)[kTestDeviceIndex0][0];
    323   EXPECT_TRUE(entry0.Equals(test_entry));
    324 
    325   // Add a second entry for a different interface.
    326   SendRouteEntry(RTNLMessage::kModeAdd,
    327                  kTestDeviceIndex1,
    328                  entry0);
    329 
    330   // We should have two tables, which should have a single entry each.
    331   EXPECT_EQ(2, tables->size());
    332   EXPECT_TRUE(ContainsKey(*tables, kTestDeviceIndex1));
    333   EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
    334   EXPECT_EQ(1, (*tables)[kTestDeviceIndex1].size());
    335 
    336   test_entry = (*tables)[kTestDeviceIndex1][0];
    337   EXPECT_TRUE(entry0.Equals(test_entry));
    338 
    339   IPAddress gateway_address1(IPAddress::kFamilyIPv4);
    340   gateway_address1.SetAddressFromString(kTestNetAddress1);
    341 
    342   RoutingTableEntry entry1(default_address,
    343                            default_address,
    344                            gateway_address1,
    345                            metric,
    346                            RT_SCOPE_UNIVERSE,
    347                            true);
    348 
    349   // Add a second gateway route to the second interface.
    350   SendRouteEntry(RTNLMessage::kModeAdd,
    351                  kTestDeviceIndex1,
    352                  entry1);
    353 
    354   // We should have two tables, one of which has a single entry, the other has
    355   // two.
    356   EXPECT_EQ(2, tables->size());
    357   EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
    358   EXPECT_EQ(2, (*tables)[kTestDeviceIndex1].size());
    359 
    360   test_entry = (*tables)[kTestDeviceIndex1][1];
    361   EXPECT_TRUE(entry1.Equals(test_entry));
    362 
    363   // Remove the first gateway route from the second interface.
    364   SendRouteEntry(RTNLMessage::kModeDelete,
    365                  kTestDeviceIndex1,
    366                  entry0);
    367 
    368   // We should be back to having one route per table.
    369   EXPECT_EQ(2, tables->size());
    370   EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
    371   EXPECT_EQ(1, (*tables)[kTestDeviceIndex1].size());
    372 
    373   test_entry = (*tables)[kTestDeviceIndex1][0];
    374   EXPECT_TRUE(entry1.Equals(test_entry));
    375 
    376   // Send a duplicate of the second gateway route message, changing the metric.
    377   RoutingTableEntry entry2(entry1);
    378   entry2.metric++;
    379   SendRouteEntry(RTNLMessage::kModeAdd,
    380                  kTestDeviceIndex1,
    381                  entry2);
    382 
    383   // Routing table size shouldn't change, but the new metric should match.
    384   EXPECT_EQ(1, (*tables)[kTestDeviceIndex1].size());
    385   test_entry = (*tables)[kTestDeviceIndex1][0];
    386   EXPECT_TRUE(entry2.Equals(test_entry));
    387 
    388   // Find a matching entry.
    389   EXPECT_TRUE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
    390                                               IPAddress::kFamilyIPv4,
    391                                               &test_entry));
    392   EXPECT_TRUE(entry2.Equals(test_entry));
    393 
    394   // Test that a search for a non-matching family fails.
    395   EXPECT_FALSE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
    396                                                IPAddress::kFamilyIPv6,
    397                                                &test_entry));
    398 
    399   // Remove last entry from an existing interface and test that we now fail.
    400   SendRouteEntry(RTNLMessage::kModeDelete,
    401                  kTestDeviceIndex1,
    402                  entry2);
    403 
    404   EXPECT_FALSE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
    405                                                IPAddress::kFamilyIPv4,
    406                                                &test_entry));
    407 
    408   // Add a route to a gateway address.
    409   IPAddress gateway_address(IPAddress::kFamilyIPv4);
    410   EXPECT_TRUE(gateway_address.SetAddressFromString(kTestNetAddress0));
    411 
    412   EXPECT_CALL(rtnl_handler_,
    413               SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
    414                                           kTestDeviceIndex1,
    415                                           entry0,
    416                                           NLM_F_CREATE | NLM_F_EXCL)));
    417   EXPECT_TRUE(routing_table_->SetDefaultRoute(kTestDeviceIndex1,
    418                                               gateway_address,
    419                                               metric,
    420                                               kTestTableId));
    421 
    422   // The table entry should look much like entry0, except with
    423   // from_rtnl = false.
    424   RoutingTableEntry entry3(entry0);
    425   entry3.from_rtnl = false;
    426   EXPECT_TRUE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
    427                                               IPAddress::kFamilyIPv4,
    428                                               &test_entry));
    429   EXPECT_TRUE(entry3.Equals(test_entry));
    430 
    431   // Setting the same route on the interface with a different metric should
    432   // push the route with different flags to indicate we are replacing it,
    433   // then it should delete the old entry.
    434   RoutingTableEntry entry4(entry3);
    435   entry4.metric += 10;
    436   EXPECT_CALL(rtnl_handler_,
    437               SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
    438                                           kTestDeviceIndex1,
    439                                           entry4,
    440                                           NLM_F_CREATE | NLM_F_REPLACE)));
    441   EXPECT_CALL(rtnl_handler_,
    442               SendMessage(IsRoutingPacket(RTNLMessage::kModeDelete,
    443                                    kTestDeviceIndex1,
    444                                    entry3,
    445                                    0)));
    446   EXPECT_TRUE(routing_table_->SetDefaultRoute(kTestDeviceIndex1,
    447                                               gateway_address,
    448                                               entry4.metric,
    449                                               kTestTableId));
    450 
    451   // Test that removing the table causes the route to disappear.
    452   routing_table_->ResetTable(kTestDeviceIndex1);
    453   EXPECT_FALSE(ContainsKey(*tables, kTestDeviceIndex1));
    454   EXPECT_FALSE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
    455                                                IPAddress::kFamilyIPv4,
    456                                                &test_entry));
    457   EXPECT_EQ(1, GetRoutingTables()->size());
    458 
    459   // When we set the metric on an existing route, a new add and delete
    460   // operation should occur.
    461   RoutingTableEntry entry5(entry4);
    462   entry5.metric += 10;
    463   EXPECT_CALL(rtnl_handler_,
    464               SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
    465                                           kTestDeviceIndex0,
    466                                           entry5,
    467                                           NLM_F_CREATE | NLM_F_REPLACE)));
    468   EXPECT_CALL(rtnl_handler_,
    469               SendMessage(IsRoutingPacket(RTNLMessage::kModeDelete,
    470                                           kTestDeviceIndex0,
    471                                           entry0,
    472                                           0)));
    473   routing_table_->SetDefaultMetric(kTestDeviceIndex0, entry5.metric);
    474   // Furthermore, the routing table should reflect the change in the metric
    475   // for the default route for the interface.
    476   RoutingTableEntry default_route;
    477   EXPECT_TRUE(routing_table_->GetDefaultRoute(kTestDeviceIndex0,
    478                                               IPAddress::kFamilyIPv4,
    479                                               &default_route));
    480   EXPECT_EQ(entry5.metric, default_route.metric);
    481 
    482   // Ask to flush table0.  We should see a delete message sent.
    483   EXPECT_CALL(rtnl_handler_,
    484               SendMessage(IsRoutingPacket(RTNLMessage::kModeDelete,
    485                                           kTestDeviceIndex0,
    486                                           entry5,
    487                                           0)));
    488   routing_table_->FlushRoutes(kTestDeviceIndex0);
    489   EXPECT_EQ(0, (*tables)[kTestDeviceIndex0].size());
    490 
    491   // Test that the routing table size returns to zero.
    492   SendRouteEntry(RTNLMessage::kModeAdd,
    493                  kTestDeviceIndex0,
    494                  entry5);
    495   EXPECT_EQ(1, GetRoutingTables()->size());
    496   routing_table_->ResetTable(kTestDeviceIndex0);
    497   EXPECT_EQ(0, GetRoutingTables()->size());
    498 
    499   routing_table_->Stop();
    500 }
    501 
    502 TEST_F(RoutingTableTest, ConfigureRoutes) {
    503   MockControl control;
    504   IPConfigRefPtr ipconfig(new IPConfig(&control, kTestDeviceName0));
    505   IPConfig::Properties properties;
    506   properties.address_family = IPAddress::kFamilyIPv4;
    507   vector<IPConfig::Route>& routes = properties.routes;
    508   ipconfig->UpdateProperties(properties, true);
    509 
    510   const int kMetric = 10;
    511   EXPECT_TRUE(routing_table_->ConfigureRoutes(kTestDeviceIndex0,
    512                                              ipconfig,
    513                                              kMetric,
    514                                              kTestTableId));
    515 
    516   IPConfig::Route route;
    517   route.host = kTestRemoteNetwork4;
    518   route.netmask = kTestRemoteNetmask4;
    519   route.gateway = kTestGatewayAddress4;
    520   routes.push_back(route);
    521   ipconfig->UpdateProperties(properties, true);
    522 
    523   IPAddress destination_address(IPAddress::kFamilyIPv4);
    524   IPAddress source_address(IPAddress::kFamilyIPv4);
    525   IPAddress gateway_address(IPAddress::kFamilyIPv4);
    526   ASSERT_TRUE(destination_address.SetAddressFromString(kTestRemoteNetwork4));
    527   destination_address.set_prefix(kTestRemotePrefix4);
    528   ASSERT_TRUE(gateway_address.SetAddressFromString(kTestGatewayAddress4));
    529 
    530   RoutingTableEntry entry(destination_address,
    531                           source_address,
    532                           gateway_address,
    533                           kMetric,
    534                           RT_SCOPE_UNIVERSE,
    535                           false,
    536                           kTestTableId,
    537                           RoutingTableEntry::kDefaultTag);
    538 
    539   EXPECT_CALL(rtnl_handler_,
    540               SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
    541                                           kTestDeviceIndex0,
    542                                           entry,
    543                                           NLM_F_CREATE | NLM_F_EXCL)));
    544   EXPECT_TRUE(routing_table_->ConfigureRoutes(kTestDeviceIndex0,
    545                                               ipconfig,
    546                                               kMetric,
    547                                               kTestTableId));
    548 
    549   routes.clear();
    550   route.gateway = "xxx";  // Invalid gateway entry -- should be skipped
    551   routes.push_back(route);
    552   route.host = "xxx";  // Invalid host entry -- should be skipped
    553   route.gateway = kTestGatewayAddress4;
    554   routes.push_back(route);
    555   route.host = kTestRemoteNetwork4;
    556   routes.push_back(route);
    557   ipconfig->UpdateProperties(properties, true);
    558 
    559   EXPECT_CALL(rtnl_handler_,
    560               SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
    561                                           kTestDeviceIndex0,
    562                                           entry,
    563                                           NLM_F_CREATE | NLM_F_EXCL)))
    564       .Times(1);
    565   EXPECT_FALSE(routing_table_->ConfigureRoutes(kTestDeviceIndex0,
    566                                                ipconfig,
    567                                                kMetric,
    568                                                kTestTableId));
    569 }
    570 
    571 MATCHER_P2(IsRoutingQuery, destination, index, "") {
    572   const RTNLMessage::RouteStatus& status = arg->route_status();
    573 
    574   uint32_t oif;
    575 
    576   return
    577       arg->type() == RTNLMessage::kTypeRoute &&
    578       arg->family() == destination.family() &&
    579       arg->flags() == NLM_F_REQUEST &&
    580       status.table == 0 &&
    581       status.protocol == 0 &&
    582       status.scope == 0 &&
    583       status.type == 0 &&
    584       arg->HasAttribute(RTA_DST) &&
    585       IPAddress(arg->family(),
    586                 arg->GetAttribute(RTA_DST),
    587                 status.dst_prefix).Equals(destination) &&
    588       !arg->HasAttribute(RTA_SRC) &&
    589       !arg->HasAttribute(RTA_GATEWAY) &&
    590       arg->GetAttribute(RTA_OIF).ConvertToCPUUInt32(&oif) &&
    591       oif == index &&
    592       !arg->HasAttribute(RTA_PRIORITY);
    593 
    594   return false;
    595 }
    596 
    597 TEST_F(RoutingTableTest, RequestHostRoute) {
    598   IPAddress destination_address(IPAddress::kFamilyIPv4);
    599   destination_address.SetAddressFromString(kTestRemoteAddress4);
    600   destination_address.set_prefix(24);
    601 
    602   EXPECT_CALL(rtnl_handler_,
    603               SendMessage(IsRoutingQuery(destination_address,
    604                                          kTestDeviceIndex0)))
    605       .WillOnce(Invoke(this, &RoutingTableTest::SetSequenceForMessage));
    606   EXPECT_TRUE(
    607       routing_table_->RequestRouteToHost(destination_address,
    608                                          kTestDeviceIndex0,
    609                                          kTestRouteTag,
    610                                          RoutingTable::Query::Callback(),
    611                                          kTestTableId));
    612 
    613   IPAddress gateway_address(IPAddress::kFamilyIPv4);
    614   gateway_address.SetAddressFromString(kTestGatewayAddress4);
    615 
    616   IPAddress local_address(IPAddress::kFamilyIPv4);
    617   local_address.SetAddressFromString(kTestDeviceNetAddress4);
    618 
    619   const int kMetric = 10;
    620   RoutingTableEntry entry(destination_address,
    621                           local_address,
    622                           gateway_address,
    623                           kMetric,
    624                           RT_SCOPE_UNIVERSE,
    625                           true,
    626                           kTestTableId,
    627                           RoutingTableEntry::kDefaultTag);
    628 
    629   EXPECT_CALL(rtnl_handler_,
    630               SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
    631                                           kTestDeviceIndex0,
    632                                           entry,
    633                                           NLM_F_CREATE | NLM_F_EXCL)));
    634   SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
    635                                 kTestDeviceIndex0,
    636                                 entry,
    637                                 kTestRequestSeq,
    638                                 RTPROT_UNSPEC);
    639 
    640   std::unordered_map<int, vector<RoutingTableEntry>>* tables =
    641       GetRoutingTables();
    642 
    643   // We should have a single table, which should in turn have a single entry.
    644   EXPECT_EQ(1, tables->size());
    645   EXPECT_TRUE(ContainsKey(*tables, kTestDeviceIndex0));
    646   EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
    647 
    648   // This entry's tag should match the tag we requested.
    649   EXPECT_EQ(kTestRouteTag, (*tables)[kTestDeviceIndex0][0].tag);
    650 
    651   EXPECT_TRUE(GetQueries()->empty());
    652 
    653   // Ask to flush routes with our tag.  We should see a delete message sent.
    654   EXPECT_CALL(rtnl_handler_,
    655               SendMessage(IsRoutingPacket(RTNLMessage::kModeDelete,
    656                                           kTestDeviceIndex0,
    657                                           entry,
    658                                           0)));
    659 
    660   routing_table_->FlushRoutesWithTag(kTestRouteTag);
    661 
    662   // After flushing routes for this tag, we should end up with no routes.
    663   EXPECT_EQ(0, (*tables)[kTestDeviceIndex0].size());
    664 }
    665 
    666 TEST_F(RoutingTableTest, RequestHostRouteWithoutGateway) {
    667   IPAddress destination_address(IPAddress::kFamilyIPv4);
    668   destination_address.SetAddressFromString(kTestRemoteAddress4);
    669   destination_address.set_prefix(24);
    670 
    671   EXPECT_CALL(rtnl_handler_,
    672               SendMessage(IsRoutingQuery(destination_address,
    673                                          kTestDeviceIndex0)))
    674       .WillOnce(Invoke(this, &RoutingTableTest::SetSequenceForMessage));
    675   EXPECT_TRUE(
    676       routing_table_->RequestRouteToHost(destination_address,
    677                                          kTestDeviceIndex0,
    678                                          kTestRouteTag,
    679                                          RoutingTable::Query::Callback(),
    680                                          kTestTableId));
    681 
    682   // Don't specify a gateway address.
    683   IPAddress gateway_address(IPAddress::kFamilyIPv4);
    684 
    685   IPAddress local_address(IPAddress::kFamilyIPv4);
    686   local_address.SetAddressFromString(kTestDeviceNetAddress4);
    687 
    688   const int kMetric = 10;
    689   RoutingTableEntry entry(destination_address,
    690                           local_address,
    691                           gateway_address,
    692                           kMetric,
    693                           RT_SCOPE_UNIVERSE,
    694                           true);
    695 
    696   // Ensure that without a gateway entry, we don't create a route.
    697   EXPECT_CALL(rtnl_handler_, SendMessage(_)).Times(0);
    698   SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
    699                                 kTestDeviceIndex0,
    700                                 entry,
    701                                 kTestRequestSeq,
    702                                 RTPROT_UNSPEC);
    703   EXPECT_TRUE(GetQueries()->empty());
    704 }
    705 
    706 TEST_F(RoutingTableTest, RequestHostRouteBadSequence) {
    707   IPAddress destination_address(IPAddress::kFamilyIPv4);
    708   destination_address.SetAddressFromString(kTestRemoteAddress4);
    709   QueryCallbackTarget target;
    710   EXPECT_CALL(target, MockedTarget(_, _)).Times(0);
    711   EXPECT_CALL(rtnl_handler_, SendMessage(_))
    712       .WillOnce(Invoke(this, &RoutingTableTest::SetSequenceForMessage));
    713   EXPECT_TRUE(
    714       routing_table_->RequestRouteToHost(destination_address,
    715                                          kTestDeviceIndex0,
    716                                          kTestRouteTag,
    717                                          target.mocked_callback(),
    718                                          kTestTableId));
    719   EXPECT_FALSE(GetQueries()->empty());
    720 
    721   RoutingTableEntry entry(destination_address,
    722                           destination_address,
    723                           destination_address,
    724                           0,
    725                           RT_SCOPE_UNIVERSE,
    726                           true);
    727 
    728   // Try a sequence arriving before the one RoutingTable is looking for.
    729   // This should be a no-op.
    730   SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
    731                                 kTestDeviceIndex0,
    732                                 entry,
    733                                 kTestRequestSeq - 1,
    734                                 RTPROT_UNSPEC);
    735   EXPECT_FALSE(GetQueries()->empty());
    736 
    737   // Try a sequence arriving after the one RoutingTable is looking for.
    738   // This should cause the request to be purged.
    739   SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
    740                                 kTestDeviceIndex0,
    741                                 entry,
    742                                 kTestRequestSeq + 1,
    743                                 RTPROT_UNSPEC);
    744   EXPECT_TRUE(GetQueries()->empty());
    745 }
    746 
    747 TEST_F(RoutingTableTest, RequestHostRouteWithCallback) {
    748   IPAddress destination_address(IPAddress::kFamilyIPv4);
    749 
    750   EXPECT_CALL(rtnl_handler_, SendMessage(_))
    751       .WillOnce(Invoke(this, &RoutingTableTest::SetSequenceForMessage));
    752   QueryCallbackTarget target;
    753   EXPECT_TRUE(
    754       routing_table_->RequestRouteToHost(destination_address,
    755                                          -1,
    756                                          kTestRouteTag,
    757                                          target.mocked_callback(),
    758                                          kTestTableId));
    759 
    760   IPAddress gateway_address(IPAddress::kFamilyIPv4);
    761   gateway_address.SetAddressFromString(kTestGatewayAddress4);
    762 
    763   const int kMetric = 10;
    764   RoutingTableEntry entry(destination_address,
    765                           IPAddress(IPAddress::kFamilyIPv4),
    766                           gateway_address,
    767                           kMetric,
    768                           RT_SCOPE_UNIVERSE,
    769                           true);
    770 
    771   EXPECT_CALL(rtnl_handler_, SendMessage(_));
    772   EXPECT_CALL(target,
    773               MockedTarget(kTestDeviceIndex0,
    774                            Field(&RoutingTableEntry::tag, kTestRouteTag)));
    775   SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
    776                                 kTestDeviceIndex0,
    777                                 entry,
    778                                 kTestRequestSeq,
    779                                 RTPROT_UNSPEC);
    780 }
    781 
    782 TEST_F(RoutingTableTest, RequestHostRouteWithoutGatewayWithCallback) {
    783   IPAddress destination_address(IPAddress::kFamilyIPv4);
    784 
    785   EXPECT_CALL(rtnl_handler_, SendMessage(_))
    786       .WillOnce(Invoke(this, &RoutingTableTest::SetSequenceForMessage));
    787   QueryCallbackTarget target;
    788   EXPECT_TRUE(
    789       routing_table_->RequestRouteToHost(destination_address,
    790                                          -1,
    791                                          kTestRouteTag,
    792                                          target.mocked_callback(),
    793                                          kTestTableId));
    794 
    795   const int kMetric = 10;
    796   RoutingTableEntry entry(destination_address,
    797                           IPAddress(IPAddress::kFamilyIPv4),
    798                           IPAddress(IPAddress::kFamilyIPv4),
    799                           kMetric,
    800                           RT_SCOPE_UNIVERSE,
    801                           true);
    802 
    803   EXPECT_CALL(target,
    804               MockedTarget(kTestDeviceIndex0,
    805                            Field(&RoutingTableEntry::tag, kTestRouteTag)));
    806   SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
    807                                 kTestDeviceIndex0,
    808                                 entry,
    809                                 kTestRequestSeq,
    810                                 RTPROT_UNSPEC);
    811 }
    812 
    813 TEST_F(RoutingTableTest, CancelQueryCallback) {
    814   IPAddress destination_address(IPAddress::kFamilyIPv4);
    815   destination_address.SetAddressFromString(kTestRemoteAddress4);
    816   std::unique_ptr<QueryCallbackTarget> target(new QueryCallbackTarget());
    817   EXPECT_CALL(rtnl_handler_, SendMessage(_))
    818       .WillOnce(Invoke(this, &RoutingTableTest::SetSequenceForMessage));
    819   EXPECT_TRUE(
    820       routing_table_->RequestRouteToHost(destination_address,
    821                                          kTestDeviceIndex0,
    822                                          kTestRouteTag,
    823                                          target->unreached_callback(),
    824                                          kTestTableId));
    825   ASSERT_EQ(1, GetQueries()->size());
    826   // Cancels the callback by destroying the owner object.
    827   target.reset();
    828   const int kMetric = 10;
    829   RoutingTableEntry entry(IPAddress(IPAddress::kFamilyIPv4),
    830                           IPAddress(IPAddress::kFamilyIPv4),
    831                           IPAddress(IPAddress::kFamilyIPv4),
    832                           kMetric,
    833                           RT_SCOPE_UNIVERSE,
    834                           true);
    835   SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
    836                                 kTestDeviceIndex0,
    837                                 entry,
    838                                 kTestRequestSeq,
    839                                 RTPROT_UNSPEC);
    840 }
    841 
    842 TEST_F(RoutingTableTest, CreateBlackholeRoute) {
    843   const uint32_t kMetric = 2;
    844   EXPECT_CALL(rtnl_handler_,
    845               SendMessage(IsBlackholeRoutingPacket(kTestDeviceIndex0,
    846                                                    IPAddress::kFamilyIPv6,
    847                                                    kMetric)))
    848       .Times(1);
    849   EXPECT_TRUE(routing_table_->CreateBlackholeRoute(kTestDeviceIndex0,
    850                                                    IPAddress::kFamilyIPv6,
    851                                                    kMetric,
    852                                                    kTestTableId));
    853 }
    854 
    855 TEST_F(RoutingTableTest, CreateLinkRoute) {
    856   IPAddress local_address(IPAddress::kFamilyIPv4);
    857   ASSERT_TRUE(local_address.SetAddressFromString(kTestNetAddress0));
    858   local_address.set_prefix(kTestRemotePrefix4);
    859   IPAddress remote_address(IPAddress::kFamilyIPv4);
    860   ASSERT_TRUE(remote_address.SetAddressFromString(kTestNetAddress1));
    861   IPAddress default_address(IPAddress::kFamilyIPv4);
    862   IPAddress remote_address_with_prefix(remote_address);
    863   remote_address_with_prefix.set_prefix(
    864       IPAddress::GetMaxPrefixLength(remote_address_with_prefix.family()));
    865   RoutingTableEntry entry(remote_address_with_prefix,
    866                           local_address,
    867                           default_address,
    868                           0,
    869                           RT_SCOPE_LINK,
    870                           false,
    871                           kTestTableId,
    872                           RoutingTableEntry::kDefaultTag);
    873   EXPECT_CALL(rtnl_handler_,
    874               SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
    875                                           kTestDeviceIndex0,
    876                                           entry,
    877                                           NLM_F_CREATE | NLM_F_EXCL)))
    878       .Times(1);
    879   EXPECT_TRUE(routing_table_->CreateLinkRoute(kTestDeviceIndex0,
    880                                               local_address,
    881                                               remote_address,
    882                                               kTestTableId));
    883 
    884   ASSERT_TRUE(remote_address.SetAddressFromString(kTestRemoteAddress4));
    885   EXPECT_FALSE(routing_table_->CreateLinkRoute(kTestDeviceIndex0,
    886                                                local_address,
    887                                                remote_address,
    888                                                kTestTableId));
    889 }
    890 
    891 }  // namespace shill
    892