• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
CreateInputHandler(int,const IOHandler::InputCallback &,const IOHandler::ErrorCallback &)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 
RoutingTableTest()69   RoutingTableTest() : routing_table_(new RoutingTable()) {}
70 
SetUp()71   virtual void SetUp() {
72     routing_table_->rtnl_handler_ = &rtnl_handler_;
73     ON_CALL(rtnl_handler_, SendMessage(_)).WillByDefault(Return(true));
74   }
75 
TearDown()76   virtual void TearDown() {
77     RTNLHandler::GetInstance()->Stop();
78   }
79 
GetRoutingTables()80   std::unordered_map<int, vector<RoutingTableEntry>>* GetRoutingTables() {
81     return &routing_table_->tables_;
82   }
83 
GetQueries()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 
SetSequenceForMessage(RTNLMessage * message)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:
QueryCallbackTarget()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 
UnreachedTarget(int interface_index,const RoutingTableEntry & entry)136     void UnreachedTarget(int interface_index, const RoutingTableEntry& entry) {
137       CHECK(false);
138     }
139 
mocked_callback() const140     const RoutingTable::Query::Callback& mocked_callback() const {
141       return mocked_callback_;
142     }
143 
unreached_callback() const144     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 
SendRouteEntry(RTNLMessage::Mode mode,uint32_t interface_index,const RoutingTableEntry & entry)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 
SendRouteEntryWithSeqAndProto(RTNLMessage::Mode mode,uint32_t interface_index,const RoutingTableEntry & entry,uint32_t seq,unsigned char proto)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 
SendRouteMessage(const RTNLMessage & msg)280 void RoutingTableTest::SendRouteMessage(const RTNLMessage& msg) {
281   routing_table_->RouteMsgHandler(msg);
282 }
283 
TEST_F(RoutingTableTest,Start)284 TEST_F(RoutingTableTest, Start) {
285   EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestRoute));
286   routing_table_->Start();
287 }
288 
TEST_F(RoutingTableTest,RouteAddDelete)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 
TEST_F(RoutingTableTest,ConfigureRoutes)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 
TEST_F(RoutingTableTest,RequestHostRoute)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 
TEST_F(RoutingTableTest,RequestHostRouteWithoutGateway)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 
TEST_F(RoutingTableTest,RequestHostRouteBadSequence)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 
TEST_F(RoutingTableTest,RequestHostRouteWithCallback)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 
TEST_F(RoutingTableTest,RequestHostRouteWithoutGatewayWithCallback)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 
TEST_F(RoutingTableTest,CancelQueryCallback)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 
TEST_F(RoutingTableTest,CreateBlackholeRoute)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 
TEST_F(RoutingTableTest,CreateLinkRoute)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