blob: 5c74f280e0cd35b01af1c4a99f5b6f60099a1a26 [file] [log] [blame]
Thieu Le3426c8f2012-01-11 17:35:11 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Paul Stewartdd60e452011-08-08 11:38:36 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Paul Stewart9a908082011-08-31 12:18:48 -07005#include <arpa/inet.h>
6#include <linux/rtnetlink.h>
7
Paul Stewartc8f4bef2011-12-13 09:45:51 -08008#include <string>
Paul Stewart9a908082011-08-31 12:18:48 -07009#include <vector>
10
11#include <base/memory/scoped_ptr.h>
Paul Stewartdd60e452011-08-08 11:38:36 -070012#include <gtest/gtest.h>
13#include <gmock/gmock.h>
14
15#include "shill/connection.h"
Paul Stewartdd60e452011-08-08 11:38:36 -070016#include "shill/ipconfig.h"
17#include "shill/mock_control.h"
Paul Stewartc8f4bef2011-12-13 09:45:51 -080018#include "shill/mock_device.h"
Paul Stewart9a908082011-08-31 12:18:48 -070019#include "shill/mock_device_info.h"
Paul Stewartdd60e452011-08-08 11:38:36 -070020#include "shill/mock_resolver.h"
21#include "shill/mock_routing_table.h"
22#include "shill/mock_rtnl_handler.h"
23#include "shill/routing_table_entry.h"
24
Paul Stewartc8f4bef2011-12-13 09:45:51 -080025using std::string;
Paul Stewart9a908082011-08-31 12:18:48 -070026using std::vector;
Paul Stewartdd60e452011-08-08 11:38:36 -070027using testing::_;
28using testing::NiceMock;
29using testing::Return;
30using testing::StrictMock;
31using testing::Test;
32
33namespace shill {
34
35namespace {
36const char kTestDeviceName0[] = "netdev0";
37const int kTestDeviceInterfaceIndex0 = 123;
38const char kTestDeviceName1[] = "netdev1";
39const int kTestDeviceInterfaceIndex1 = 321;
40const char kIPAddress0[] = "192.168.1.1";
41const char kGatewayAddress0[] = "192.168.1.254";
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070042const char kGatewayAddress1[] = "192.168.2.254";
Paul Stewart9a908082011-08-31 12:18:48 -070043const char kBroadcastAddress0[] = "192.168.1.255";
Paul Stewartdd60e452011-08-08 11:38:36 -070044const char kNameServer0[] = "8.8.8.8";
45const char kNameServer1[] = "8.8.9.9";
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070046const int32 kPrefix0 = 24;
47const int32 kPrefix1 = 31;
Paul Stewartdd60e452011-08-08 11:38:36 -070048const char kSearchDomain0[] = "chromium.org";
49const char kSearchDomain1[] = "google.com";
50} // namespace {}
51
52class ConnectionTest : public Test {
53 public:
54 ConnectionTest()
Paul Stewart9a908082011-08-31 12:18:48 -070055 : device_info_(new StrictMock<MockDeviceInfo>(
56 &control_,
57 static_cast<EventDispatcher*>(NULL),
Thieu Le3426c8f2012-01-11 17:35:11 -080058 static_cast<Metrics*>(NULL),
Paul Stewart9a908082011-08-31 12:18:48 -070059 static_cast<Manager*>(NULL))),
60 connection_(new Connection(
61 kTestDeviceInterfaceIndex0,
62 kTestDeviceName0,
Paul Stewarte00600e2012-03-16 07:08:00 -070063 Technology::kUnknown,
Paul Stewart9a908082011-08-31 12:18:48 -070064 device_info_.get())),
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070065 ipconfig_(new IPConfig(&control_, kTestDeviceName0)),
66 local_address_(IPAddress::kFamilyIPv4),
67 broadcast_address_(IPAddress::kFamilyIPv4),
68 gateway_address_(IPAddress::kFamilyIPv4),
69 default_address_(IPAddress::kFamilyIPv4) {}
Paul Stewartdd60e452011-08-08 11:38:36 -070070
71 virtual void SetUp() {
Paul Stewartc8f4bef2011-12-13 09:45:51 -080072 ReplaceSingletons(connection_);
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070073 properties_.address = kIPAddress0;
74 properties_.subnet_prefix = kPrefix0;
75 properties_.gateway = kGatewayAddress0;
76 properties_.broadcast_address = kBroadcastAddress0;
77 properties_.dns_servers.push_back(kNameServer0);
78 properties_.dns_servers.push_back(kNameServer1);
79 properties_.domain_search.push_back(kSearchDomain0);
80 properties_.domain_search.push_back(kSearchDomain1);
81 properties_.address_family = IPAddress::kFamilyIPv4;
82 UpdateProperties();
83 EXPECT_TRUE(local_address_.SetAddressFromString(kIPAddress0));
84 EXPECT_TRUE(broadcast_address_.SetAddressFromString(kBroadcastAddress0));
85 EXPECT_TRUE(gateway_address_.SetAddressFromString(kGatewayAddress0));
Paul Stewartdd60e452011-08-08 11:38:36 -070086 }
87
Paul Stewart9a908082011-08-31 12:18:48 -070088 virtual void TearDown() {
89 EXPECT_CALL(*device_info_, FlushAddresses(kTestDeviceInterfaceIndex0));
Paul Stewarte93b0382012-04-24 13:11:28 -070090 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex0));
91 EXPECT_CALL(routing_table_, FlushRoutesWithTag(kTestDeviceInterfaceIndex0));
92 connection_ = NULL;
Paul Stewart9a908082011-08-31 12:18:48 -070093 }
94
Paul Stewartc8f4bef2011-12-13 09:45:51 -080095 void ReplaceSingletons(ConnectionRefPtr connection) {
96 connection->resolver_ = &resolver_;
97 connection->routing_table_ = &routing_table_;
98 connection->rtnl_handler_ = &rtnl_handler_;
99 }
100
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700101 void UpdateProperties() {
102 ipconfig_->UpdateProperties(properties_, true);
103 }
104
Paul Stewarte93b0382012-04-24 13:11:28 -0700105 bool PinHostRoute(ConnectionRefPtr connection,
106 const IPConfig::Properties &properties) {
107 return connection->PinHostRoute(properties);
108 }
109
Paul Stewartdd60e452011-08-08 11:38:36 -0700110 protected:
Paul Stewart9a908082011-08-31 12:18:48 -0700111 scoped_ptr<StrictMock<MockDeviceInfo> > device_info_;
Paul Stewartdd60e452011-08-08 11:38:36 -0700112 ConnectionRefPtr connection_;
113 MockControl control_;
114 IPConfigRefPtr ipconfig_;
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700115 IPConfig::Properties properties_;
116 IPAddress local_address_;
117 IPAddress broadcast_address_;
118 IPAddress gateway_address_;
119 IPAddress default_address_;
Paul Stewartdd60e452011-08-08 11:38:36 -0700120 StrictMock<MockResolver> resolver_;
121 StrictMock<MockRoutingTable> routing_table_;
122 StrictMock<MockRTNLHandler> rtnl_handler_;
123};
124
125TEST_F(ConnectionTest, InitState) {
126 EXPECT_EQ(kTestDeviceInterfaceIndex0, connection_->interface_index_);
127 EXPECT_EQ(kTestDeviceName0, connection_->interface_name_);
128 EXPECT_FALSE(connection_->is_default());
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800129 EXPECT_FALSE(connection_->routing_request_count_);
Paul Stewartdd60e452011-08-08 11:38:36 -0700130}
131
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700132MATCHER_P2(IsIPAddress, address, prefix, "") {
133 IPAddress match_address(address);
134 match_address.set_prefix(prefix);
135 return match_address.Equals(arg);
136}
137
Paul Stewartdd60e452011-08-08 11:38:36 -0700138TEST_F(ConnectionTest, AddConfig) {
139 EXPECT_CALL(rtnl_handler_,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700140 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
141 IsIPAddress(local_address_, kPrefix0),
142 IsIPAddress(broadcast_address_, 0),
143 IsIPAddress(default_address_, 0)));
Paul Stewart7cfca042011-12-08 14:18:17 -0800144 EXPECT_CALL(routing_table_,
145 SetDefaultRoute(kTestDeviceInterfaceIndex0,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700146 IsIPAddress(gateway_address_, 0),
Paul Stewart7cfca042011-12-08 14:18:17 -0800147 Connection::kNonDefaultMetricBase +
148 kTestDeviceInterfaceIndex0));
Paul Stewart3f68bb12012-03-15 13:33:10 -0700149 EXPECT_CALL(routing_table_,
150 ConfigureRoutes(kTestDeviceInterfaceIndex0,
151 ipconfig_,
152 Connection::kDefaultMetric));
Paul Stewartdd60e452011-08-08 11:38:36 -0700153 connection_->UpdateFromIPConfig(ipconfig_);
154
155 EXPECT_CALL(routing_table_, SetDefaultMetric(kTestDeviceInterfaceIndex0,
156 Connection::kDefaultMetric));
157 EXPECT_CALL(resolver_, SetDNSFromLists(
158 ipconfig_->properties().dns_servers,
159 ipconfig_->properties().domain_search));
160
Paul Stewartc681fa02012-03-02 19:40:04 -0800161 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
162 &control_,
163 reinterpret_cast<EventDispatcher *>(NULL),
164 reinterpret_cast<Metrics *>(NULL),
165 reinterpret_cast<Manager *>(NULL),
166 kTestDeviceName0,
167 string(),
168 kTestDeviceInterfaceIndex0));
169 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
170 .WillOnce(Return(device));
171 EXPECT_CALL(*device.get(), RequestPortalDetection())
172 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800173 connection_->SetIsDefault(true);
Paul Stewartdd60e452011-08-08 11:38:36 -0700174 EXPECT_TRUE(connection_->is_default());
175
Paul Stewart7cfca042011-12-08 14:18:17 -0800176 EXPECT_CALL(routing_table_,
177 SetDefaultMetric(kTestDeviceInterfaceIndex0,
178 Connection::kNonDefaultMetricBase +
179 kTestDeviceInterfaceIndex0));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800180 connection_->SetIsDefault(false);
Paul Stewartdd60e452011-08-08 11:38:36 -0700181 EXPECT_FALSE(connection_->is_default());
182}
183
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700184TEST_F(ConnectionTest, AddConfigWithPeer) {
185 const string kPeerAddress("192.168.1.222");
186 IPAddress peer_address(IPAddress::kFamilyIPv4);
187 EXPECT_TRUE(peer_address.SetAddressFromString(kPeerAddress));
188 properties_.peer_address = kPeerAddress;
189 properties_.gateway = string();
190 UpdateProperties();
191 EXPECT_CALL(rtnl_handler_,
192 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
193 IsIPAddress(local_address_, kPrefix0),
194 IsIPAddress(broadcast_address_, 0),
195 IsIPAddress(peer_address, 0)));
196 EXPECT_CALL(routing_table_, SetDefaultRoute(_, _, _)).Times(0);
197 EXPECT_CALL(routing_table_,
198 ConfigureRoutes(kTestDeviceInterfaceIndex0,
199 ipconfig_,
200 Connection::kDefaultMetric));
201 connection_->UpdateFromIPConfig(ipconfig_);
202}
203
204TEST_F(ConnectionTest, AddConfigWithBrokenNetmask) {
205 // Assign a prefix that makes the gateway unreachable.
206 properties_.subnet_prefix = kPrefix1;
207 UpdateProperties();
208
209 // Connection should override with a prefix which will allow the
210 // gateway to be reachable.
211 EXPECT_CALL(rtnl_handler_,
212 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
213 IsIPAddress(local_address_, kPrefix0),
214 IsIPAddress(broadcast_address_, 0),
215 IsIPAddress(default_address_, 0)));
216 EXPECT_CALL(routing_table_,
217 SetDefaultRoute(kTestDeviceInterfaceIndex0,
218 IsIPAddress(gateway_address_, 0),
219 Connection::kNonDefaultMetricBase +
220 kTestDeviceInterfaceIndex0));
221 EXPECT_CALL(routing_table_,
222 ConfigureRoutes(kTestDeviceInterfaceIndex0,
223 ipconfig_,
224 Connection::kDefaultMetric));
225 connection_->UpdateFromIPConfig(ipconfig_);
226
227 // Assign a gateway address that violates the minimum plausible prefix
228 // the Connection can assign.
229 properties_.gateway = kGatewayAddress1;
230 UpdateProperties();
231
232 // Connection cannot override this prefix, so it will revert to the
233 // configured prefix, expecting the default route to fail.
234 EXPECT_CALL(rtnl_handler_,
235 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
236 IsIPAddress(local_address_, kPrefix1),
237 IsIPAddress(broadcast_address_, 0),
238 IsIPAddress(default_address_, 0)));
239 EXPECT_CALL(routing_table_,
240 SetDefaultRoute(kTestDeviceInterfaceIndex0, _, _));
241 EXPECT_CALL(routing_table_,
242 ConfigureRoutes(kTestDeviceInterfaceIndex0, _, _));
243 connection_->UpdateFromIPConfig(ipconfig_);
244}
245
Paul Stewartdd60e452011-08-08 11:38:36 -0700246TEST_F(ConnectionTest, AddConfigReverse) {
247 EXPECT_CALL(routing_table_, SetDefaultMetric(kTestDeviceInterfaceIndex0,
248 Connection::kDefaultMetric));
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800249 vector<string> empty_list;
Paul Stewartdd60e452011-08-08 11:38:36 -0700250 EXPECT_CALL(resolver_, SetDNSFromLists(empty_list, empty_list));
Paul Stewartc681fa02012-03-02 19:40:04 -0800251 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
252 &control_,
253 reinterpret_cast<EventDispatcher *>(NULL),
254 reinterpret_cast<Metrics *>(NULL),
255 reinterpret_cast<Manager *>(NULL),
256 kTestDeviceName0,
257 string(),
258 kTestDeviceInterfaceIndex0));
259 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
260 .WillOnce(Return(device));
261 EXPECT_CALL(*device.get(), RequestPortalDetection())
262 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800263 connection_->SetIsDefault(true);
Paul Stewartdd60e452011-08-08 11:38:36 -0700264
265 EXPECT_CALL(rtnl_handler_,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700266 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
267 IsIPAddress(local_address_, kPrefix0),
268 IsIPAddress(broadcast_address_, 0),
269 IsIPAddress(default_address_, 0)));
Paul Stewartdd60e452011-08-08 11:38:36 -0700270 EXPECT_CALL(routing_table_, SetDefaultRoute(kTestDeviceInterfaceIndex0,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700271 IsIPAddress(gateway_address_, 0),
272 Connection::kDefaultMetric));
Paul Stewart3f68bb12012-03-15 13:33:10 -0700273 EXPECT_CALL(routing_table_,
274 ConfigureRoutes(kTestDeviceInterfaceIndex0,
275 ipconfig_,
276 Connection::kDefaultMetric));
Paul Stewartdd60e452011-08-08 11:38:36 -0700277 EXPECT_CALL(resolver_, SetDNSFromIPConfig(ipconfig_));
278
279 connection_->UpdateFromIPConfig(ipconfig_);
280}
281
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800282TEST_F(ConnectionTest, RouteRequest) {
Paul Stewartf748a362012-03-07 12:01:20 -0800283 ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex0,
284 kTestDeviceName0,
Paul Stewarte00600e2012-03-16 07:08:00 -0700285 Technology::kUnknown,
Paul Stewartf748a362012-03-07 12:01:20 -0800286 device_info_.get()));
287 ReplaceSingletons(connection);
288 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
289 &control_,
290 reinterpret_cast<EventDispatcher *>(NULL),
291 reinterpret_cast<Metrics *>(NULL),
292 reinterpret_cast<Manager *>(NULL),
293 kTestDeviceName0,
294 string(),
295 kTestDeviceInterfaceIndex0));
296 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
297 .WillRepeatedly(Return(device));
298 EXPECT_CALL(*device.get(), DisableReversePathFilter()).Times(1);
299 connection->RequestRouting();
300 connection->RequestRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800301
Paul Stewartf748a362012-03-07 12:01:20 -0800302 // The first release should only decrement the reference counter.
303 connection->ReleaseRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800304
Paul Stewartf748a362012-03-07 12:01:20 -0800305 // Another release will re-enable reverse-path filter.
306 EXPECT_CALL(*device.get(), EnableReversePathFilter());
307 EXPECT_CALL(routing_table_, FlushCache());
308 connection->ReleaseRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800309
Paul Stewartf748a362012-03-07 12:01:20 -0800310 // The destructor will remove the routes and addresses.
311 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex0));
Paul Stewarte93b0382012-04-24 13:11:28 -0700312 EXPECT_CALL(routing_table_, FlushRoutesWithTag(kTestDeviceInterfaceIndex0));
Paul Stewartf748a362012-03-07 12:01:20 -0800313 EXPECT_CALL(*device_info_.get(),
314 FlushAddresses(kTestDeviceInterfaceIndex0));
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800315}
316
Paul Stewartdd60e452011-08-08 11:38:36 -0700317TEST_F(ConnectionTest, Destructor) {
Thieu Lefb46caf2012-03-08 11:57:15 -0800318 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex1));
Paul Stewarte93b0382012-04-24 13:11:28 -0700319 EXPECT_CALL(routing_table_, FlushRoutesWithTag(kTestDeviceInterfaceIndex1));
Paul Stewart9a908082011-08-31 12:18:48 -0700320 EXPECT_CALL(*device_info_, FlushAddresses(kTestDeviceInterfaceIndex1));
Paul Stewartdd60e452011-08-08 11:38:36 -0700321 {
322 ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex1,
Paul Stewart9a908082011-08-31 12:18:48 -0700323 kTestDeviceName1,
Paul Stewarte00600e2012-03-16 07:08:00 -0700324 Technology::kUnknown,
Paul Stewart9a908082011-08-31 12:18:48 -0700325 device_info_.get()));
Paul Stewartdd60e452011-08-08 11:38:36 -0700326 connection->resolver_ = &resolver_;
327 connection->routing_table_ = &routing_table_;
328 connection->rtnl_handler_ = &rtnl_handler_;
329 }
330}
331
Paul Stewartf748a362012-03-07 12:01:20 -0800332TEST_F(ConnectionTest, RequestHostRoute) {
333 ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex0,
334 kTestDeviceName0,
Paul Stewarte00600e2012-03-16 07:08:00 -0700335 Technology::kUnknown,
Paul Stewartf748a362012-03-07 12:01:20 -0800336 device_info_.get()));
337 ReplaceSingletons(connection);
338 IPAddress address(IPAddress::kFamilyIPv4);
339 ASSERT_TRUE(address.SetAddressFromString(kIPAddress0));
340 size_t prefix_len = address.GetLength() * 8;
341 EXPECT_CALL(routing_table_, RequestRouteToHost(
Paul Stewarte93b0382012-04-24 13:11:28 -0700342 IsIPAddress(address, prefix_len), -1, kTestDeviceInterfaceIndex0))
Paul Stewartf748a362012-03-07 12:01:20 -0800343 .WillOnce(Return(true));
344 EXPECT_TRUE(connection->RequestHostRoute(address));
345
346 // The destructor will remove the routes and addresses.
347 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex0));
Paul Stewarte93b0382012-04-24 13:11:28 -0700348 EXPECT_CALL(routing_table_, FlushRoutesWithTag(kTestDeviceInterfaceIndex0));
349 EXPECT_CALL(*device_info_.get(),
350 FlushAddresses(kTestDeviceInterfaceIndex0));
351}
352
353TEST_F(ConnectionTest, PinHostRoute) {
354 static const char kGateway[] = "10.242.2.13";
355 static const char kNetwork[] = "10.242.2.1";
356
357 ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex0,
358 kTestDeviceName0,
359 Technology::kUnknown,
360 device_info_.get()));
361 ReplaceSingletons(connection);
362
363 IPConfig::Properties props;
364 props.address_family = IPAddress::kFamilyIPv4;
365 EXPECT_FALSE(PinHostRoute(connection, props));
366
367 props.gateway = kGateway;
368 EXPECT_FALSE(PinHostRoute(connection, props));
369
370 props.gateway.clear();
371 props.trusted_ip = "xxx";
372 EXPECT_FALSE(PinHostRoute(connection, props));
373
374 props.gateway = kGateway;
375 EXPECT_FALSE(PinHostRoute(connection, props));
376
377 props.trusted_ip = kNetwork;
378 IPAddress address(IPAddress::kFamilyIPv4);
379 ASSERT_TRUE(address.SetAddressFromString(kNetwork));
380 size_t prefix_len = address.GetLength() * 8;
381 EXPECT_CALL(routing_table_, RequestRouteToHost(
382 IsIPAddress(address, prefix_len), -1, kTestDeviceInterfaceIndex0))
383 .WillOnce(Return(false));
384 EXPECT_FALSE(PinHostRoute(connection, props));
385
386 EXPECT_CALL(routing_table_, RequestRouteToHost(
387 IsIPAddress(address, prefix_len), -1, kTestDeviceInterfaceIndex0))
388 .WillOnce(Return(true));
389 EXPECT_TRUE(PinHostRoute(connection, props));
390
391 // The destructor will remove the routes and addresses.
392 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex0));
393 EXPECT_CALL(routing_table_, FlushRoutesWithTag(kTestDeviceInterfaceIndex0));
Paul Stewartf748a362012-03-07 12:01:20 -0800394 EXPECT_CALL(*device_info_.get(),
395 FlushAddresses(kTestDeviceInterfaceIndex0));
396}
397
Paul Stewartdd60e452011-08-08 11:38:36 -0700398} // namespace shill