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
41using base::Bind;
42using base::Callback;
43using base::Unretained;
44using std::deque;
45using std::vector;
46using testing::_;
47using testing::Field;
48using testing::Invoke;
49using testing::Return;
50using testing::StrictMock;
51using testing::Test;
52
53namespace shill {
54
55class 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
65class 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
159const uint32_t RoutingTableTest::kTestDeviceIndex0 = 12345;
160const uint32_t RoutingTableTest::kTestDeviceIndex1 = 67890;
161const char RoutingTableTest::kTestDeviceName0[] = "test-device0";
162const char RoutingTableTest::kTestDeviceNetAddress4[] = "192.168.2.0/24";
163const char RoutingTableTest::kTestForeignNetAddress4[] = "192.168.2.2";
164const char RoutingTableTest::kTestForeignNetGateway4[] = "192.168.2.1";
165const char RoutingTableTest::kTestForeignNetAddress6[] = "2000::/3";
166const char RoutingTableTest::kTestForeignNetGateway6[] = "fe80:::::1";
167const char RoutingTableTest::kTestGatewayAddress4[] = "192.168.2.254";
168const char RoutingTableTest::kTestNetAddress0[] = "192.168.1.1";
169const char RoutingTableTest::kTestNetAddress1[] = "192.168.1.2";
170const char RoutingTableTest::kTestRemoteAddress4[] = "192.168.2.254";
171const char RoutingTableTest::kTestRemoteNetmask4[] = "255.255.255.0";
172const char RoutingTableTest::kTestRemoteNetwork4[] = "192.168.100.0";
173const int RoutingTableTest::kTestRemotePrefix4 = 24;
174const uint32_t RoutingTableTest::kTestRequestSeq = 456;
175const int RoutingTableTest::kTestRouteTag = 789;
176const uint8_t RoutingTableTest::kTestTableId = 0xa5;
177
178namespace {
179
180MATCHER_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
203MATCHER_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
237void 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
243void 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
280void RoutingTableTest::SendRouteMessage(const RTNLMessage& msg) {
281  routing_table_->RouteMsgHandler(msg);
282}
283
284TEST_F(RoutingTableTest, Start) {
285  EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestRoute));
286  routing_table_->Start();
287}
288
289TEST_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
502TEST_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
571MATCHER_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
597TEST_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
666TEST_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
706TEST_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
747TEST_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
782TEST_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
813TEST_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
842TEST_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
855TEST_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