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