blob: e99f55a584bae450702bba4ecc8e454f290c75e2 [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"
Darin Petkov13e6d552012-05-09 14:22:23 +020017#include "shill/mock_connection.h"
Paul Stewartdd60e452011-08-08 11:38:36 -070018#include "shill/mock_control.h"
Paul Stewartc8f4bef2011-12-13 09:45:51 -080019#include "shill/mock_device.h"
Paul Stewart9a908082011-08-31 12:18:48 -070020#include "shill/mock_device_info.h"
Paul Stewartdd60e452011-08-08 11:38:36 -070021#include "shill/mock_resolver.h"
22#include "shill/mock_routing_table.h"
23#include "shill/mock_rtnl_handler.h"
24#include "shill/routing_table_entry.h"
25
Paul Stewartc8f4bef2011-12-13 09:45:51 -080026using std::string;
Paul Stewart9a908082011-08-31 12:18:48 -070027using std::vector;
Paul Stewartdd60e452011-08-08 11:38:36 -070028using testing::_;
Paul Stewarte78ec542012-06-08 18:28:50 -070029using testing::Mock;
Paul Stewartdd60e452011-08-08 11:38:36 -070030using testing::NiceMock;
31using testing::Return;
Paul Stewart4a6748d2012-07-17 14:31:36 -070032using testing::ReturnRef;
Paul Stewartdd60e452011-08-08 11:38:36 -070033using testing::StrictMock;
34using testing::Test;
35
36namespace shill {
37
38namespace {
39const char kTestDeviceName0[] = "netdev0";
40const int kTestDeviceInterfaceIndex0 = 123;
41const char kTestDeviceName1[] = "netdev1";
42const int kTestDeviceInterfaceIndex1 = 321;
43const char kIPAddress0[] = "192.168.1.1";
44const char kGatewayAddress0[] = "192.168.1.254";
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070045const char kGatewayAddress1[] = "192.168.2.254";
Paul Stewart9a908082011-08-31 12:18:48 -070046const char kBroadcastAddress0[] = "192.168.1.255";
Paul Stewartdd60e452011-08-08 11:38:36 -070047const char kNameServer0[] = "8.8.8.8";
48const char kNameServer1[] = "8.8.9.9";
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070049const int32 kPrefix0 = 24;
50const int32 kPrefix1 = 31;
Paul Stewartdd60e452011-08-08 11:38:36 -070051const char kSearchDomain0[] = "chromium.org";
52const char kSearchDomain1[] = "google.com";
53} // namespace {}
54
55class ConnectionTest : public Test {
56 public:
57 ConnectionTest()
Paul Stewart9a908082011-08-31 12:18:48 -070058 : device_info_(new StrictMock<MockDeviceInfo>(
59 &control_,
60 static_cast<EventDispatcher*>(NULL),
Thieu Le3426c8f2012-01-11 17:35:11 -080061 static_cast<Metrics*>(NULL),
Paul Stewart9a908082011-08-31 12:18:48 -070062 static_cast<Manager*>(NULL))),
63 connection_(new Connection(
64 kTestDeviceInterfaceIndex0,
65 kTestDeviceName0,
Paul Stewarte00600e2012-03-16 07:08:00 -070066 Technology::kUnknown,
Paul Stewart9a908082011-08-31 12:18:48 -070067 device_info_.get())),
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070068 ipconfig_(new IPConfig(&control_, kTestDeviceName0)),
69 local_address_(IPAddress::kFamilyIPv4),
70 broadcast_address_(IPAddress::kFamilyIPv4),
71 gateway_address_(IPAddress::kFamilyIPv4),
72 default_address_(IPAddress::kFamilyIPv4) {}
Paul Stewartdd60e452011-08-08 11:38:36 -070073
74 virtual void SetUp() {
Paul Stewartc8f4bef2011-12-13 09:45:51 -080075 ReplaceSingletons(connection_);
Paul Stewart5b7ba8c2012-04-18 09:08:00 -070076 properties_.address = kIPAddress0;
77 properties_.subnet_prefix = kPrefix0;
78 properties_.gateway = kGatewayAddress0;
79 properties_.broadcast_address = kBroadcastAddress0;
80 properties_.dns_servers.push_back(kNameServer0);
81 properties_.dns_servers.push_back(kNameServer1);
82 properties_.domain_search.push_back(kSearchDomain0);
83 properties_.domain_search.push_back(kSearchDomain1);
84 properties_.address_family = IPAddress::kFamilyIPv4;
85 UpdateProperties();
86 EXPECT_TRUE(local_address_.SetAddressFromString(kIPAddress0));
87 EXPECT_TRUE(broadcast_address_.SetAddressFromString(kBroadcastAddress0));
88 EXPECT_TRUE(gateway_address_.SetAddressFromString(kGatewayAddress0));
Paul Stewartdd60e452011-08-08 11:38:36 -070089 }
90
Paul Stewart9a908082011-08-31 12:18:48 -070091 virtual void TearDown() {
Darin Petkov13e6d552012-05-09 14:22:23 +020092 AddDestructorExpectations();
Paul Stewarte93b0382012-04-24 13:11:28 -070093 connection_ = NULL;
Paul Stewart9a908082011-08-31 12:18:48 -070094 }
95
Paul Stewartc8f4bef2011-12-13 09:45:51 -080096 void ReplaceSingletons(ConnectionRefPtr connection) {
97 connection->resolver_ = &resolver_;
98 connection->routing_table_ = &routing_table_;
99 connection->rtnl_handler_ = &rtnl_handler_;
100 }
101
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700102 void UpdateProperties() {
103 ipconfig_->UpdateProperties(properties_, true);
104 }
105
Paul Stewarte93b0382012-04-24 13:11:28 -0700106 bool PinHostRoute(ConnectionRefPtr connection,
107 const IPConfig::Properties &properties) {
108 return connection->PinHostRoute(properties);
109 }
110
Paul Stewart4a6748d2012-07-17 14:31:36 -0700111 const IPAddress &GetLocalAddress(ConnectionRefPtr connection) {
112 return connection->local_;
113 }
114
115 const IPAddress &GetGatewayAddress(ConnectionRefPtr connection) {
116 return connection->gateway_;
117 }
118
119 bool GetHasBroadcastDomain(ConnectionRefPtr connection) {
120 return connection->has_broadcast_domain_;
121 }
122
Paul Stewart05a42c22012-08-02 16:47:21 -0700123 uint32 GetDefaultMetric() {
124 return Connection::kDefaultMetric;
125 }
126
127 uint32 GetNonDefaultMetricBase() {
128 return Connection::kNonDefaultMetricBase;
129 }
130
Paul Stewartdd60e452011-08-08 11:38:36 -0700131 protected:
Darin Petkov13e6d552012-05-09 14:22:23 +0200132 class DisconnectCallbackTarget {
133 public:
134 DisconnectCallbackTarget()
135 : callback_(base::Bind(&DisconnectCallbackTarget::CallTarget,
136 base::Unretained(this))) {}
137
138 MOCK_METHOD0(CallTarget, void());
139 const base::Closure &callback() { return callback_; }
140
141 private:
142 base::Closure callback_;
143 };
144
145 void AddDestructorExpectations() {
146 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex0));
147 EXPECT_CALL(routing_table_, FlushRoutesWithTag(kTestDeviceInterfaceIndex0));
148 EXPECT_CALL(*device_info_.get(),
149 FlushAddresses(kTestDeviceInterfaceIndex0));
150 }
151
152 // Returns a new test connection object. The caller usually needs to call
153 // AddDestructorExpectations before destroying the object.
154 ConnectionRefPtr GetNewConnection() {
155 ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex0,
156 kTestDeviceName0,
157 Technology::kUnknown,
158 device_info_.get()));
159 ReplaceSingletons(connection);
160 return connection;
161 }
162
Paul Stewart9a908082011-08-31 12:18:48 -0700163 scoped_ptr<StrictMock<MockDeviceInfo> > device_info_;
Paul Stewartdd60e452011-08-08 11:38:36 -0700164 ConnectionRefPtr connection_;
165 MockControl control_;
166 IPConfigRefPtr ipconfig_;
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700167 IPConfig::Properties properties_;
168 IPAddress local_address_;
169 IPAddress broadcast_address_;
170 IPAddress gateway_address_;
171 IPAddress default_address_;
Paul Stewartdd60e452011-08-08 11:38:36 -0700172 StrictMock<MockResolver> resolver_;
173 StrictMock<MockRoutingTable> routing_table_;
174 StrictMock<MockRTNLHandler> rtnl_handler_;
175};
176
Darin Petkov13e6d552012-05-09 14:22:23 +0200177namespace {
Paul Stewartdd60e452011-08-08 11:38:36 -0700178
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700179MATCHER_P2(IsIPAddress, address, prefix, "") {
180 IPAddress match_address(address);
181 match_address.set_prefix(prefix);
182 return match_address.Equals(arg);
183}
184
Darin Petkov13e6d552012-05-09 14:22:23 +0200185MATCHER(IsNonNullCallback, "") {
186 return !arg.is_null();
187}
188
189} // namespace
190
191TEST_F(ConnectionTest, InitState) {
192 EXPECT_EQ(kTestDeviceInterfaceIndex0, connection_->interface_index_);
193 EXPECT_EQ(kTestDeviceName0, connection_->interface_name_);
194 EXPECT_FALSE(connection_->is_default());
195 EXPECT_FALSE(connection_->routing_request_count_);
196}
197
Paul Stewartdd60e452011-08-08 11:38:36 -0700198TEST_F(ConnectionTest, AddConfig) {
Paul Stewart05a42c22012-08-02 16:47:21 -0700199 EXPECT_CALL(*device_info_,
200 HasOtherAddress(kTestDeviceInterfaceIndex0,
201 IsIPAddress(local_address_, kPrefix0)))
202 .WillOnce(Return(false));
Paul Stewartdd60e452011-08-08 11:38:36 -0700203 EXPECT_CALL(rtnl_handler_,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700204 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
205 IsIPAddress(local_address_, kPrefix0),
206 IsIPAddress(broadcast_address_, 0),
207 IsIPAddress(default_address_, 0)));
Paul Stewart7cfca042011-12-08 14:18:17 -0800208 EXPECT_CALL(routing_table_,
209 SetDefaultRoute(kTestDeviceInterfaceIndex0,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700210 IsIPAddress(gateway_address_, 0),
Paul Stewart05a42c22012-08-02 16:47:21 -0700211 GetNonDefaultMetricBase() +
Paul Stewart7cfca042011-12-08 14:18:17 -0800212 kTestDeviceInterfaceIndex0));
Paul Stewart3f68bb12012-03-15 13:33:10 -0700213 EXPECT_CALL(routing_table_,
214 ConfigureRoutes(kTestDeviceInterfaceIndex0,
215 ipconfig_,
Paul Stewart05a42c22012-08-02 16:47:21 -0700216 GetDefaultMetric()));
Paul Stewartdd60e452011-08-08 11:38:36 -0700217 connection_->UpdateFromIPConfig(ipconfig_);
Paul Stewart4a6748d2012-07-17 14:31:36 -0700218 IPAddress test_local_address(local_address_);
219 test_local_address.set_prefix(kPrefix0);
220 EXPECT_TRUE(test_local_address.Equals(GetLocalAddress(connection_)));
221 EXPECT_TRUE(gateway_address_.Equals(GetGatewayAddress(connection_)));
222 EXPECT_TRUE(GetHasBroadcastDomain(connection_));
223
224 EXPECT_CALL(routing_table_,
225 CreateLinkRoute(kTestDeviceInterfaceIndex0,
226 IsIPAddress(local_address_, kPrefix0),
227 IsIPAddress(gateway_address_, 0)))
228 .WillOnce(Return(true))
229 .WillOnce(Return(false));
230 EXPECT_TRUE(connection_->CreateGatewayRoute());
231 EXPECT_FALSE(connection_->CreateGatewayRoute());
232 connection_->has_broadcast_domain_ = false;
233 EXPECT_FALSE(connection_->CreateGatewayRoute());
Paul Stewartdd60e452011-08-08 11:38:36 -0700234
235 EXPECT_CALL(routing_table_, SetDefaultMetric(kTestDeviceInterfaceIndex0,
Paul Stewart05a42c22012-08-02 16:47:21 -0700236 GetDefaultMetric()));
Paul Stewartdd60e452011-08-08 11:38:36 -0700237 EXPECT_CALL(resolver_, SetDNSFromLists(
238 ipconfig_->properties().dns_servers,
239 ipconfig_->properties().domain_search));
240
Paul Stewartc681fa02012-03-02 19:40:04 -0800241 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
242 &control_,
243 reinterpret_cast<EventDispatcher *>(NULL),
244 reinterpret_cast<Metrics *>(NULL),
245 reinterpret_cast<Manager *>(NULL),
246 kTestDeviceName0,
247 string(),
248 kTestDeviceInterfaceIndex0));
249 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
250 .WillOnce(Return(device));
251 EXPECT_CALL(*device.get(), RequestPortalDetection())
252 .WillOnce(Return(true));
Paul Stewarte78ec542012-06-08 18:28:50 -0700253 EXPECT_CALL(routing_table_, FlushCache())
254 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800255 connection_->SetIsDefault(true);
Paul Stewarte78ec542012-06-08 18:28:50 -0700256 Mock::VerifyAndClearExpectations(&routing_table_);
Paul Stewartdd60e452011-08-08 11:38:36 -0700257 EXPECT_TRUE(connection_->is_default());
258
Paul Stewart7cfca042011-12-08 14:18:17 -0800259 EXPECT_CALL(routing_table_,
260 SetDefaultMetric(kTestDeviceInterfaceIndex0,
Paul Stewart05a42c22012-08-02 16:47:21 -0700261 GetNonDefaultMetricBase() +
Paul Stewart7cfca042011-12-08 14:18:17 -0800262 kTestDeviceInterfaceIndex0));
Paul Stewarte78ec542012-06-08 18:28:50 -0700263 EXPECT_CALL(routing_table_, FlushCache())
264 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800265 connection_->SetIsDefault(false);
Paul Stewartdd60e452011-08-08 11:38:36 -0700266 EXPECT_FALSE(connection_->is_default());
267}
268
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700269TEST_F(ConnectionTest, AddConfigWithPeer) {
270 const string kPeerAddress("192.168.1.222");
271 IPAddress peer_address(IPAddress::kFamilyIPv4);
272 EXPECT_TRUE(peer_address.SetAddressFromString(kPeerAddress));
273 properties_.peer_address = kPeerAddress;
274 properties_.gateway = string();
275 UpdateProperties();
Paul Stewart05a42c22012-08-02 16:47:21 -0700276 EXPECT_CALL(*device_info_,
277 HasOtherAddress(kTestDeviceInterfaceIndex0,
278 IsIPAddress(local_address_, kPrefix0)))
279 .WillOnce(Return(false));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700280 EXPECT_CALL(rtnl_handler_,
281 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
282 IsIPAddress(local_address_, kPrefix0),
283 IsIPAddress(broadcast_address_, 0),
284 IsIPAddress(peer_address, 0)));
285 EXPECT_CALL(routing_table_, SetDefaultRoute(_, _, _)).Times(0);
286 EXPECT_CALL(routing_table_,
287 ConfigureRoutes(kTestDeviceInterfaceIndex0,
288 ipconfig_,
Paul Stewart05a42c22012-08-02 16:47:21 -0700289 GetDefaultMetric()));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700290 connection_->UpdateFromIPConfig(ipconfig_);
Paul Stewart4a6748d2012-07-17 14:31:36 -0700291 EXPECT_FALSE(GetHasBroadcastDomain(connection_));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700292}
293
294TEST_F(ConnectionTest, AddConfigWithBrokenNetmask) {
295 // Assign a prefix that makes the gateway unreachable.
296 properties_.subnet_prefix = kPrefix1;
297 UpdateProperties();
298
299 // Connection should override with a prefix which will allow the
300 // gateway to be reachable.
Paul Stewart05a42c22012-08-02 16:47:21 -0700301 EXPECT_CALL(*device_info_,
302 HasOtherAddress(kTestDeviceInterfaceIndex0,
303 IsIPAddress(local_address_, kPrefix0)))
304 .WillOnce(Return(false));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700305 EXPECT_CALL(rtnl_handler_,
306 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
307 IsIPAddress(local_address_, kPrefix0),
308 IsIPAddress(broadcast_address_, 0),
309 IsIPAddress(default_address_, 0)));
310 EXPECT_CALL(routing_table_,
311 SetDefaultRoute(kTestDeviceInterfaceIndex0,
312 IsIPAddress(gateway_address_, 0),
Paul Stewart05a42c22012-08-02 16:47:21 -0700313 GetNonDefaultMetricBase() +
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700314 kTestDeviceInterfaceIndex0));
315 EXPECT_CALL(routing_table_,
316 ConfigureRoutes(kTestDeviceInterfaceIndex0,
317 ipconfig_,
Paul Stewart05a42c22012-08-02 16:47:21 -0700318 GetDefaultMetric()));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700319 connection_->UpdateFromIPConfig(ipconfig_);
320
321 // Assign a gateway address that violates the minimum plausible prefix
322 // the Connection can assign.
323 properties_.gateway = kGatewayAddress1;
324 UpdateProperties();
325
Paul Stewart49258292012-05-26 06:37:14 -0700326 IPAddress gateway_address1(IPAddress::kFamilyIPv4);
327 EXPECT_TRUE(gateway_address1.SetAddressFromString(kGatewayAddress1));
328 // Connection cannot override this prefix, so it will switch to a
329 // model where the peer address is set to the value of the gateway
330 // address.
Paul Stewart05a42c22012-08-02 16:47:21 -0700331 EXPECT_CALL(*device_info_,
332 HasOtherAddress(kTestDeviceInterfaceIndex0,
333 IsIPAddress(local_address_, kPrefix1)))
334 .WillOnce(Return(false));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700335 EXPECT_CALL(rtnl_handler_,
336 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
337 IsIPAddress(local_address_, kPrefix1),
338 IsIPAddress(broadcast_address_, 0),
Paul Stewart49258292012-05-26 06:37:14 -0700339 IsIPAddress(gateway_address1, 0)));
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700340 EXPECT_CALL(routing_table_,
341 SetDefaultRoute(kTestDeviceInterfaceIndex0, _, _));
342 EXPECT_CALL(routing_table_,
343 ConfigureRoutes(kTestDeviceInterfaceIndex0, _, _));
344 connection_->UpdateFromIPConfig(ipconfig_);
345}
346
Paul Stewartdd60e452011-08-08 11:38:36 -0700347TEST_F(ConnectionTest, AddConfigReverse) {
348 EXPECT_CALL(routing_table_, SetDefaultMetric(kTestDeviceInterfaceIndex0,
Paul Stewart05a42c22012-08-02 16:47:21 -0700349 GetDefaultMetric()));
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800350 vector<string> empty_list;
Paul Stewartdd60e452011-08-08 11:38:36 -0700351 EXPECT_CALL(resolver_, SetDNSFromLists(empty_list, empty_list));
Paul Stewartc681fa02012-03-02 19:40:04 -0800352 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
353 &control_,
354 reinterpret_cast<EventDispatcher *>(NULL),
355 reinterpret_cast<Metrics *>(NULL),
356 reinterpret_cast<Manager *>(NULL),
357 kTestDeviceName0,
358 string(),
359 kTestDeviceInterfaceIndex0));
360 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
361 .WillOnce(Return(device));
362 EXPECT_CALL(*device.get(), RequestPortalDetection())
363 .WillOnce(Return(true));
Paul Stewarte78ec542012-06-08 18:28:50 -0700364 EXPECT_CALL(routing_table_, FlushCache())
365 .WillOnce(Return(true));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800366 connection_->SetIsDefault(true);
Paul Stewarte78ec542012-06-08 18:28:50 -0700367 Mock::VerifyAndClearExpectations(&routing_table_);
Paul Stewartdd60e452011-08-08 11:38:36 -0700368
Paul Stewart05a42c22012-08-02 16:47:21 -0700369 EXPECT_CALL(*device_info_,
370 HasOtherAddress(kTestDeviceInterfaceIndex0,
371 IsIPAddress(local_address_, kPrefix0)))
372 .WillOnce(Return(false));
Paul Stewartdd60e452011-08-08 11:38:36 -0700373 EXPECT_CALL(rtnl_handler_,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700374 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
375 IsIPAddress(local_address_, kPrefix0),
376 IsIPAddress(broadcast_address_, 0),
377 IsIPAddress(default_address_, 0)));
Paul Stewartdd60e452011-08-08 11:38:36 -0700378 EXPECT_CALL(routing_table_, SetDefaultRoute(kTestDeviceInterfaceIndex0,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700379 IsIPAddress(gateway_address_, 0),
Paul Stewart05a42c22012-08-02 16:47:21 -0700380 GetDefaultMetric()));
Paul Stewart3f68bb12012-03-15 13:33:10 -0700381 EXPECT_CALL(routing_table_,
382 ConfigureRoutes(kTestDeviceInterfaceIndex0,
383 ipconfig_,
Paul Stewart05a42c22012-08-02 16:47:21 -0700384 GetDefaultMetric()));
Paul Stewartdd60e452011-08-08 11:38:36 -0700385 EXPECT_CALL(resolver_, SetDNSFromIPConfig(ipconfig_));
386
387 connection_->UpdateFromIPConfig(ipconfig_);
388}
389
Paul Stewart05a42c22012-08-02 16:47:21 -0700390TEST_F(ConnectionTest, HasOtherAddress) {
391 EXPECT_CALL(*device_info_,
392 HasOtherAddress(kTestDeviceInterfaceIndex0,
393 IsIPAddress(local_address_, kPrefix0)))
394 .WillOnce(Return(true));
395 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex0));
396 EXPECT_CALL(*device_info_, FlushAddresses(kTestDeviceInterfaceIndex0));
397 EXPECT_CALL(rtnl_handler_,
398 AddInterfaceAddress(kTestDeviceInterfaceIndex0,
399 IsIPAddress(local_address_, kPrefix0),
400 IsIPAddress(broadcast_address_, 0),
401 IsIPAddress(default_address_, 0)));
402 EXPECT_CALL(routing_table_,
403 SetDefaultRoute(kTestDeviceInterfaceIndex0,
404 IsIPAddress(gateway_address_, 0),
405 GetNonDefaultMetricBase() +
406 kTestDeviceInterfaceIndex0));
407 EXPECT_CALL(routing_table_,
408 ConfigureRoutes(kTestDeviceInterfaceIndex0,
409 ipconfig_,
410 GetDefaultMetric()));
411 connection_->UpdateFromIPConfig(ipconfig_);
412}
413
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800414TEST_F(ConnectionTest, RouteRequest) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200415 ConnectionRefPtr connection = GetNewConnection();
Paul Stewartf748a362012-03-07 12:01:20 -0800416 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
417 &control_,
418 reinterpret_cast<EventDispatcher *>(NULL),
419 reinterpret_cast<Metrics *>(NULL),
420 reinterpret_cast<Manager *>(NULL),
421 kTestDeviceName0,
422 string(),
423 kTestDeviceInterfaceIndex0));
424 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
425 .WillRepeatedly(Return(device));
426 EXPECT_CALL(*device.get(), DisableReversePathFilter()).Times(1);
427 connection->RequestRouting();
428 connection->RequestRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800429
Paul Stewartf748a362012-03-07 12:01:20 -0800430 // The first release should only decrement the reference counter.
431 connection->ReleaseRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800432
Paul Stewartf748a362012-03-07 12:01:20 -0800433 // Another release will re-enable reverse-path filter.
434 EXPECT_CALL(*device.get(), EnableReversePathFilter());
435 EXPECT_CALL(routing_table_, FlushCache());
436 connection->ReleaseRouting();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800437
Paul Stewartf748a362012-03-07 12:01:20 -0800438 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200439 AddDestructorExpectations();
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800440}
441
Paul Stewartdd60e452011-08-08 11:38:36 -0700442TEST_F(ConnectionTest, Destructor) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200443 ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex1,
444 kTestDeviceName1,
445 Technology::kUnknown,
446 device_info_.get()));
447 connection->resolver_ = &resolver_;
448 connection->routing_table_ = &routing_table_;
449 connection->rtnl_handler_ = &rtnl_handler_;
Thieu Lefb46caf2012-03-08 11:57:15 -0800450 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex1));
Paul Stewarte93b0382012-04-24 13:11:28 -0700451 EXPECT_CALL(routing_table_, FlushRoutesWithTag(kTestDeviceInterfaceIndex1));
Paul Stewart9a908082011-08-31 12:18:48 -0700452 EXPECT_CALL(*device_info_, FlushAddresses(kTestDeviceInterfaceIndex1));
Darin Petkov13e6d552012-05-09 14:22:23 +0200453 connection = NULL;
Paul Stewartdd60e452011-08-08 11:38:36 -0700454}
455
Paul Stewartf748a362012-03-07 12:01:20 -0800456TEST_F(ConnectionTest, RequestHostRoute) {
Darin Petkov13e6d552012-05-09 14:22:23 +0200457 ConnectionRefPtr connection = GetNewConnection();
Paul Stewartf748a362012-03-07 12:01:20 -0800458 IPAddress address(IPAddress::kFamilyIPv4);
459 ASSERT_TRUE(address.SetAddressFromString(kIPAddress0));
460 size_t prefix_len = address.GetLength() * 8;
Darin Petkov13e6d552012-05-09 14:22:23 +0200461 EXPECT_CALL(routing_table_,
462 RequestRouteToHost(IsIPAddress(address, prefix_len),
463 -1,
464 kTestDeviceInterfaceIndex0,
465 IsNonNullCallback()))
Paul Stewartf748a362012-03-07 12:01:20 -0800466 .WillOnce(Return(true));
467 EXPECT_TRUE(connection->RequestHostRoute(address));
468
469 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200470 AddDestructorExpectations();
Paul Stewarte93b0382012-04-24 13:11:28 -0700471}
472
473TEST_F(ConnectionTest, PinHostRoute) {
474 static const char kGateway[] = "10.242.2.13";
475 static const char kNetwork[] = "10.242.2.1";
476
Darin Petkov13e6d552012-05-09 14:22:23 +0200477 ConnectionRefPtr connection = GetNewConnection();
Paul Stewarte93b0382012-04-24 13:11:28 -0700478
479 IPConfig::Properties props;
480 props.address_family = IPAddress::kFamilyIPv4;
481 EXPECT_FALSE(PinHostRoute(connection, props));
482
483 props.gateway = kGateway;
484 EXPECT_FALSE(PinHostRoute(connection, props));
485
486 props.gateway.clear();
487 props.trusted_ip = "xxx";
488 EXPECT_FALSE(PinHostRoute(connection, props));
489
490 props.gateway = kGateway;
491 EXPECT_FALSE(PinHostRoute(connection, props));
492
493 props.trusted_ip = kNetwork;
494 IPAddress address(IPAddress::kFamilyIPv4);
495 ASSERT_TRUE(address.SetAddressFromString(kNetwork));
496 size_t prefix_len = address.GetLength() * 8;
497 EXPECT_CALL(routing_table_, RequestRouteToHost(
Darin Petkovabf6d282012-05-08 15:49:05 +0200498 IsIPAddress(address, prefix_len), -1, kTestDeviceInterfaceIndex0, _))
Paul Stewarte93b0382012-04-24 13:11:28 -0700499 .WillOnce(Return(false));
500 EXPECT_FALSE(PinHostRoute(connection, props));
501
502 EXPECT_CALL(routing_table_, RequestRouteToHost(
Darin Petkovabf6d282012-05-08 15:49:05 +0200503 IsIPAddress(address, prefix_len), -1, kTestDeviceInterfaceIndex0, _))
Paul Stewarte93b0382012-04-24 13:11:28 -0700504 .WillOnce(Return(true));
505 EXPECT_TRUE(PinHostRoute(connection, props));
506
507 // The destructor will remove the routes and addresses.
Darin Petkov13e6d552012-05-09 14:22:23 +0200508 AddDestructorExpectations();
Paul Stewartf748a362012-03-07 12:01:20 -0800509}
510
Paul Stewart53a30382012-04-26 09:06:59 -0700511TEST_F(ConnectionTest, FixGatewayReachability) {
512 static const char kLocal[] = "10.242.2.13";
513 IPAddress local(IPAddress::kFamilyIPv4);
514 ASSERT_TRUE(local.SetAddressFromString(kLocal));
515 const int kPrefix = 24;
516 local.set_prefix(kPrefix);
517 IPAddress gateway(IPAddress::kFamilyIPv4);
518 IPAddress peer(IPAddress::kFamilyIPv4);
519
520 // Should fail because no gateway is set.
Paul Stewart49258292012-05-26 06:37:14 -0700521 EXPECT_FALSE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700522 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700523 EXPECT_FALSE(peer.IsValid());
Paul Stewart53a30382012-04-26 09:06:59 -0700524
525 // Should succeed because with the given prefix, this gateway is reachable.
526 static const char kReachableGateway[] = "10.242.2.14";
527 ASSERT_TRUE(gateway.SetAddressFromString(kReachableGateway));
Paul Stewart49258292012-05-26 06:37:14 -0700528 peer = IPAddress(IPAddress::kFamilyIPv4);
529 EXPECT_TRUE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700530 // Prefix should remain unchanged.
531 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700532 // Peer should remain unchanged.
533 EXPECT_FALSE(peer.IsValid());
Paul Stewart53a30382012-04-26 09:06:59 -0700534
535 // Should succeed because we modified the prefix to match the gateway.
536 static const char kExpandableGateway[] = "10.242.3.14";
537 ASSERT_TRUE(gateway.SetAddressFromString(kExpandableGateway));
Paul Stewart49258292012-05-26 06:37:14 -0700538 peer = IPAddress(IPAddress::kFamilyIPv4);
539 EXPECT_TRUE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700540 // Prefix should have opened up by 1 bit.
541 EXPECT_EQ(kPrefix - 1, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700542 // Peer should remain unchanged.
543 EXPECT_FALSE(peer.IsValid());
Paul Stewart53a30382012-04-26 09:06:59 -0700544
Paul Stewart2aa5d7d2012-06-21 22:16:54 -0700545 // Should change models to assuming point-to-point because we cannot
Paul Stewart49258292012-05-26 06:37:14 -0700546 // plausibly expand the prefix past 8.
Paul Stewart53a30382012-04-26 09:06:59 -0700547 local.set_prefix(kPrefix);
548 static const char kUnreachableGateway[] = "11.242.2.14";
549 ASSERT_TRUE(gateway.SetAddressFromString(kUnreachableGateway));
Paul Stewart49258292012-05-26 06:37:14 -0700550 peer = IPAddress(IPAddress::kFamilyIPv4);
551 EXPECT_TRUE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700552 // Prefix should not have changed.
553 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700554 // Peer address should be set to the gateway address.
555 EXPECT_TRUE(peer.Equals(gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700556
Paul Stewart2aa5d7d2012-06-21 22:16:54 -0700557 // Should also use point-to-point model if the netmask is set to the
558 // "all-ones" addresss, even if this address could have been made
559 // accessible by plausibly changing the prefix.
560 const int kIPv4MaxPrefix =
561 IPAddress::GetMaxPrefixLength(IPAddress::kFamilyIPv4);
562 local.set_prefix(kIPv4MaxPrefix);
563 ASSERT_TRUE(gateway.SetAddressFromString(kExpandableGateway));
564 peer = IPAddress(IPAddress::kFamilyIPv4);
565 EXPECT_TRUE(Connection::FixGatewayReachability(&local, &peer, gateway));
566 // Prefix should not have changed.
567 EXPECT_EQ(kIPv4MaxPrefix, local.prefix());
568 // Peer address should be set to the gateway address.
569 EXPECT_TRUE(peer.Equals(gateway));
570
Paul Stewart49258292012-05-26 06:37:14 -0700571 // If this is a peer-to-peer interface and the peer matches the gateway,
572 // we should succeed.
Paul Stewart2aa5d7d2012-06-21 22:16:54 -0700573 local.set_prefix(kPrefix);
574 ASSERT_TRUE(gateway.SetAddressFromString(kUnreachableGateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700575 ASSERT_TRUE(peer.SetAddressFromString(kUnreachableGateway));
Paul Stewart49258292012-05-26 06:37:14 -0700576 EXPECT_TRUE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700577 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700578 EXPECT_TRUE(peer.Equals(gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700579
580 // If there is a peer specified and it does not match the gateway (even
581 // if it was reachable via netmask), we should fail.
582 ASSERT_TRUE(gateway.SetAddressFromString(kReachableGateway));
Paul Stewart49258292012-05-26 06:37:14 -0700583 EXPECT_FALSE(Connection::FixGatewayReachability(&local, &peer, gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700584 EXPECT_EQ(kPrefix, local.prefix());
Paul Stewart49258292012-05-26 06:37:14 -0700585 EXPECT_FALSE(peer.Equals(gateway));
Paul Stewart53a30382012-04-26 09:06:59 -0700586}
587
Darin Petkov13e6d552012-05-09 14:22:23 +0200588TEST_F(ConnectionTest, Binders) {
589 EXPECT_TRUE(connection_->binders_.empty());
590 DisconnectCallbackTarget target0;
591 DisconnectCallbackTarget target1;
592 DisconnectCallbackTarget target2;
593 DisconnectCallbackTarget target3;
594 Connection::Binder binder0("binder0", target0.callback());
595 Connection::Binder binder1("binder1", target1.callback());
596 Connection::Binder binder2("binder2", target2.callback());
597 Connection::Binder binder3("binder3", target3.callback());
598
599 binder0.Attach(connection_);
600 binder1.Attach(connection_);
601
602 EXPECT_CALL(target1, CallTarget()).Times(0);
603 binder1.Attach(connection_);
604
605 binder3.Attach(connection_);
606 binder2.Attach(connection_);
607
608 EXPECT_CALL(target3, CallTarget()).Times(0);
609 binder3.Attach(NULL);
610
611 ASSERT_EQ(3, connection_->binders_.size());
612 EXPECT_TRUE(connection_->binders_.at(0) == &binder0);
613 EXPECT_TRUE(connection_->binders_.at(1) == &binder1);
614 EXPECT_TRUE(connection_->binders_.at(2) == &binder2);
615
616 EXPECT_CALL(target0, CallTarget()).Times(1);
617 EXPECT_CALL(target1, CallTarget()).Times(1);
618 EXPECT_CALL(target2, CallTarget()).Times(1);
619 connection_->NotifyBindersOnDisconnect();
620 EXPECT_TRUE(connection_->binders_.empty());
621
622 // Should be a no-op.
623 connection_->NotifyBindersOnDisconnect();
624}
625
626TEST_F(ConnectionTest, Binder) {
627 // No connection should be bound initially.
628 Connection::Binder *binder = &connection_->lower_binder_;
629 EXPECT_EQ(connection_->interface_name(), binder->name_);
630 EXPECT_FALSE(binder->client_disconnect_callback_.is_null());
631 EXPECT_FALSE(binder->IsBound());
632
633 ConnectionRefPtr connection1 = GetNewConnection();
634 EXPECT_TRUE(connection1->binders_.empty());
635
636 // Bind lower |connection1| and check if it's bound.
637 binder->Attach(connection1);
638 EXPECT_TRUE(binder->IsBound());
639 EXPECT_EQ(connection1.get(), binder->connection().get());
640 ASSERT_FALSE(connection1->binders_.empty());
641 EXPECT_TRUE(binder == connection1->binders_.at(0));
642
643 // Unbind lower |connection1| and check if it's unbound.
644 binder->Attach(NULL);
645 EXPECT_FALSE(binder->IsBound());
646 EXPECT_TRUE(connection1->binders_.empty());
647
648 ConnectionRefPtr connection2 = GetNewConnection();
649
650 // Bind lower |connection1| to upper |connection2| and destroy the upper
651 // |connection2|. Make sure lower |connection1| is unbound (i.e., the
652 // disconnect callback is deregistered).
653 connection2->lower_binder_.Attach(connection1);
654 EXPECT_FALSE(connection1->binders_.empty());
655 AddDestructorExpectations();
656 connection2 = NULL;
657 EXPECT_TRUE(connection1->binders_.empty());
658
659 // Bind lower |connection1| to upper |connection_| and destroy lower
660 // |connection1|. Make sure lower |connection1| is unbound from upper
661 // |connection_| and upper |connection_|'s registered disconnect callbacks are
662 // run.
663 binder->Attach(connection1);
664 DisconnectCallbackTarget target;
665 Connection::Binder test_binder("from_test", target.callback());
666 test_binder.Attach(connection_);
667 EXPECT_CALL(target, CallTarget()).Times(1);
668 ASSERT_FALSE(connection_->binders_.empty());
669 AddDestructorExpectations();
670 connection1 = NULL;
671 EXPECT_FALSE(binder->IsBound());
672 EXPECT_FALSE(test_binder.IsBound());
673 EXPECT_TRUE(connection_->binders_.empty());
674
675 {
676 // Binding a connection to itself should be safe.
677 ConnectionRefPtr connection = GetNewConnection();
678
679 connection->lower_binder_.Attach(connection);
680
681 EXPECT_FALSE(connection->binders_.empty());
682
683 DisconnectCallbackTarget target;
684 Connection::Binder binder("test", target.callback());
685 binder.Attach(connection);
686
687 AddDestructorExpectations();
688 EXPECT_CALL(target, CallTarget()).Times(1);
689 connection = NULL;
690 }
Darin Petkov13e6d552012-05-09 14:22:23 +0200691 {
692 // Circular binding of multiple connections should be safe.
693 ConnectionRefPtr connection_a = GetNewConnection();
694 ConnectionRefPtr connection_b = GetNewConnection();
695
696 connection_a->lower_binder_.Attach(connection_b);
697 connection_b->lower_binder_.Attach(connection_a);
698
699 EXPECT_FALSE(connection_a->binders_.empty());
700 EXPECT_FALSE(connection_b->binders_.empty());
701
702 DisconnectCallbackTarget target_a;
703 DisconnectCallbackTarget target_b;
704 Connection::Binder binder_a("test_a", target_a.callback());
705 Connection::Binder binder_b("test_b", target_b.callback());
706 binder_a.Attach(connection_a);
707 binder_b.Attach(connection_b);
708
709 AddDestructorExpectations();
710 EXPECT_CALL(target_a, CallTarget()).Times(1);
711 EXPECT_CALL(target_b, CallTarget()).Times(1);
712 connection_b = NULL;
713
714 EXPECT_TRUE(connection_a->binders_.empty());
715
716 AddDestructorExpectations();
717 connection_a = NULL;
718 }
Darin Petkovef1f9fe2012-05-11 16:51:52 +0200719 {
720 // Test the weak pointer to the bound Connection. This is not a case that
721 // should occur but the weak pointer should handle it gracefully.
722 DisconnectCallbackTarget target;
723 Connection::Binder binder("test_weak", target.callback());
724 ConnectionRefPtr connection = GetNewConnection();
725 binder.Attach(connection);
726
727 // Make sure the connection doesn't notify the binder on destruction.
728 connection->binders_.clear();
729 AddDestructorExpectations();
730 EXPECT_CALL(target, CallTarget()).Times(0);
731 connection = NULL;
732
733 // Ensure no crash -- the weak pointer to connection should be NULL.
Darin Petkov5eb05422012-05-11 15:45:25 +0200734 EXPECT_FALSE(binder.connection());
Darin Petkovef1f9fe2012-05-11 16:51:52 +0200735 binder.Attach(NULL);
736 }
Darin Petkov13e6d552012-05-09 14:22:23 +0200737}
738
739TEST_F(ConnectionTest, OnRouteQueryResponse) {
740 Connection::Binder *binder = &connection_->lower_binder_;
741 ConnectionRefPtr connection = GetNewConnection();
742 scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
743 &control_,
744 reinterpret_cast<EventDispatcher *>(NULL),
745 reinterpret_cast<Metrics *>(NULL),
746 reinterpret_cast<Manager *>(NULL),
747 kTestDeviceName1,
748 string(),
749 kTestDeviceInterfaceIndex1));
750
751 // Make sure we unbind the old lower connection even if we can't lookup the
752 // lower connection device.
753 binder->Attach(connection);
754 scoped_refptr<MockDevice> null_device;
755 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex1))
756 .WillOnce(Return(null_device));
757 connection_->OnRouteQueryResponse(
758 kTestDeviceInterfaceIndex1, RoutingTableEntry());
759 EXPECT_FALSE(binder->IsBound());
760
761 // Check for graceful handling of a device with no connection.
762 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex1))
763 .WillOnce(Return(device));
764 connection_->OnRouteQueryResponse(
765 kTestDeviceInterfaceIndex1, RoutingTableEntry());
766 EXPECT_FALSE(binder->IsBound());
767
Paul Stewart4a6748d2012-07-17 14:31:36 -0700768 // Create a mock connection that will be used fo binding.
769 scoped_refptr<MockConnection> mock_connection(
770 new StrictMock<MockConnection>(device_info_.get()));
771 EXPECT_CALL(*device_info_.get(),
772 FlushAddresses(mock_connection->interface_index()));
773 const string kInterfaceName(kTestDeviceName0);
774 EXPECT_CALL(*mock_connection, interface_name())
775 .WillRepeatedly(ReturnRef(kInterfaceName));
776 device->connection_ = mock_connection;
Darin Petkov13e6d552012-05-09 14:22:23 +0200777 EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex1))
778 .WillOnce(Return(device));
Paul Stewart4a6748d2012-07-17 14:31:36 -0700779
780 // Check that the the binding process completes, causing its upper
781 // connection to create a gateway route.
782 EXPECT_CALL(*mock_connection, CreateGatewayRoute())
783 .WillOnce(Return(true));
Darin Petkov13e6d552012-05-09 14:22:23 +0200784 connection_->OnRouteQueryResponse(
785 kTestDeviceInterfaceIndex1, RoutingTableEntry());
Paul Stewart4a6748d2012-07-17 14:31:36 -0700786
787 // Check that the upper connection is bound to the lower connection.
Darin Petkov13e6d552012-05-09 14:22:23 +0200788 EXPECT_TRUE(binder->IsBound());
Paul Stewart4a6748d2012-07-17 14:31:36 -0700789 EXPECT_EQ(mock_connection.get(), binder->connection().get());
Darin Petkov13e6d552012-05-09 14:22:23 +0200790
791 device->connection_ = NULL;
792 AddDestructorExpectations();
793 connection = NULL;
794}
795
Paul Stewartdd60e452011-08-08 11:38:36 -0700796} // namespace shill