shill: Enable and disable reverse-path filtering
When an http proxy request is active (as well as portal check, when
that gets written), we need to initiate connections over a non-default
network interface. For this we temporarily disable reverse-path
filtering on the interface during the duration of the request.
BUG=chromium-os:24141
TEST=New unit tests for HTTPProxy and Connection
Change-Id: Ife2ad775fd8a3d2fb48f860e804eeb442dc5c58a
Reviewed-on: https://gerrit.chromium.org/gerrit/12889
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Commit-Ready: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/connection.cc b/connection.cc
index 460654d..a80271f 100644
--- a/connection.cc
+++ b/connection.cc
@@ -25,6 +25,7 @@
const std::string& interface_name,
const DeviceInfo *device_info)
: is_default_(false),
+ routing_request_count_(0),
interface_index_(interface_index),
interface_name_(interface_name),
device_info_(device_info),
@@ -37,6 +38,7 @@
Connection::~Connection() {
VLOG(2) << __func__;
+ DCHECK(!routing_request_count_);
routing_table_->FlushRoutes(interface_index_);
device_info_->FlushAddresses(interface_index_);
}
@@ -90,6 +92,35 @@
is_default_ = is_default;
}
+void Connection::RequestRouting() {
+ if (routing_request_count_++ == 0) {
+ DeviceRefPtr device = device_info_->GetDevice(interface_index_);
+ DCHECK(device.get());
+ if (!device.get()) {
+ LOG(ERROR) << "Device is NULL!";
+ return;
+ }
+ device->DisableReversePathFilter();
+ }
+}
+
+void Connection::ReleaseRouting() {
+ DCHECK(routing_request_count_ > 0);
+ if (--routing_request_count_ == 0) {
+ DeviceRefPtr device = device_info_->GetDevice(interface_index_);
+ DCHECK(device.get());
+ if (!device.get()) {
+ LOG(ERROR) << "Device is NULL!";
+ return;
+ }
+ device->EnableReversePathFilter();
+
+ // Clear any cached routes that might have accumulated while reverse-path
+ // filtering was disabled.
+ routing_table_->FlushCache();
+ }
+}
+
uint32 Connection::GetMetric(bool is_default) {
// If this is not the default route, assign a metric based on the interface
// index. This way all non-default routes (even to the same gateway IP) end
diff --git a/connection.h b/connection.h
index f99447d..93a903a 100644
--- a/connection.h
+++ b/connection.h
@@ -38,8 +38,16 @@
bool is_default() const { return is_default_; }
virtual void SetIsDefault(bool is_default);
- const std::string &interface_name() const { return interface_name_; }
- const std::vector<std::string> &dns_servers() const { return dns_servers_; }
+ virtual const std::string &interface_name() const { return interface_name_; }
+ virtual const std::vector<std::string> &dns_servers() const {
+ return dns_servers_;
+ }
+
+ // Request to accept traffic routed to this connection even if it is not
+ // the default. This request is ref-counted so the caller must call
+ // ReleaseRouting() when they no longer need this facility.
+ virtual void RequestRouting();
+ virtual void ReleaseRouting();
private:
friend class ConnectionTest;
@@ -54,6 +62,7 @@
uint32 GetMetric(bool is_default);
bool is_default_;
+ int routing_request_count_;
int interface_index_;
const std::string interface_name_;
std::vector<std::string> dns_servers_;
diff --git a/connection_unittest.cc b/connection_unittest.cc
index e5b0cba..283b069 100644
--- a/connection_unittest.cc
+++ b/connection_unittest.cc
@@ -5,6 +5,7 @@
#include <arpa/inet.h>
#include <linux/rtnetlink.h>
+#include <string>
#include <vector>
#include <base/memory/scoped_ptr.h>
@@ -14,12 +15,14 @@
#include "shill/connection.h"
#include "shill/ipconfig.h"
#include "shill/mock_control.h"
+#include "shill/mock_device.h"
#include "shill/mock_device_info.h"
#include "shill/mock_resolver.h"
#include "shill/mock_routing_table.h"
#include "shill/mock_rtnl_handler.h"
#include "shill/routing_table_entry.h"
+using std::string;
using std::vector;
using testing::_;
using testing::NiceMock;
@@ -57,10 +60,7 @@
ipconfig_(new IPConfig(&control_, kTestDeviceName0)) {}
virtual void SetUp() {
- connection_->resolver_ = &resolver_;
- connection_->routing_table_ = &routing_table_;
- connection_->rtnl_handler_ = &rtnl_handler_;
-
+ ReplaceSingletons(connection_);
IPConfig::Properties properties;
properties.address = kIPAddress0;
properties.gateway = kGatewayAddress0;
@@ -77,6 +77,12 @@
EXPECT_CALL(*device_info_, FlushAddresses(kTestDeviceInterfaceIndex0));
}
+ void ReplaceSingletons(ConnectionRefPtr connection) {
+ connection->resolver_ = &resolver_;
+ connection->routing_table_ = &routing_table_;
+ connection->rtnl_handler_ = &rtnl_handler_;
+ }
+
protected:
scoped_ptr<StrictMock<MockDeviceInfo> > device_info_;
ConnectionRefPtr connection_;
@@ -91,6 +97,7 @@
EXPECT_EQ(kTestDeviceInterfaceIndex0, connection_->interface_index_);
EXPECT_EQ(kTestDeviceName0, connection_->interface_name_);
EXPECT_FALSE(connection_->is_default());
+ EXPECT_FALSE(connection_->routing_request_count_);
}
TEST_F(ConnectionTest, AddConfig) {
@@ -123,7 +130,7 @@
TEST_F(ConnectionTest, AddConfigReverse) {
EXPECT_CALL(routing_table_, SetDefaultMetric(kTestDeviceInterfaceIndex0,
Connection::kDefaultMetric));
- vector<std::string> empty_list;
+ vector<string> empty_list;
EXPECT_CALL(resolver_, SetDNSFromLists(empty_list, empty_list));
connection_->SetIsDefault(true);
@@ -137,6 +144,40 @@
connection_->UpdateFromIPConfig(ipconfig_);
}
+TEST_F(ConnectionTest, RouteRequest) {
+ {
+ ConnectionRefPtr connection(new Connection(kTestDeviceInterfaceIndex0,
+ kTestDeviceName0,
+ device_info_.get()));
+ ReplaceSingletons(connection);
+ scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
+ &control_,
+ reinterpret_cast<EventDispatcher *>(NULL),
+ reinterpret_cast<Manager *>(NULL),
+ kTestDeviceName0,
+ string(),
+ kTestDeviceInterfaceIndex0));
+ EXPECT_CALL(*device_info_, GetDevice(kTestDeviceInterfaceIndex0))
+ .WillRepeatedly(Return(device));
+ EXPECT_CALL(*device.get(), DisableReversePathFilter()).Times(1);
+ connection->RequestRouting();
+ connection->RequestRouting();
+
+ // The first release should only decrement the reference counter.
+ connection->ReleaseRouting();
+
+ // Another release will re-enable reverse-path filter.
+ EXPECT_CALL(*device.get(), EnableReversePathFilter());
+ EXPECT_CALL(routing_table_, FlushCache());
+ connection->ReleaseRouting();
+
+ // The destructor will remove the routes and addresses.
+ EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex0));
+ EXPECT_CALL(*device_info_.get(),
+ FlushAddresses(kTestDeviceInterfaceIndex0));
+ }
+}
+
TEST_F(ConnectionTest, Destructor) {
EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex1));
EXPECT_CALL(*device_info_, FlushAddresses(kTestDeviceInterfaceIndex1));
diff --git a/device.cc b/device.cc
index 5281909..68ab81b 100644
--- a/device.cc
+++ b/device.cc
@@ -52,6 +52,12 @@
const char Device::kIPFlagUseTempAddr[] = "use_tempaddr";
// static
const char Device::kIPFlagUseTempAddrUsedAndDefault[] = "2";
+// static
+const char Device::kIPFlagReversePathFilter[] = "rp_filter";
+// static
+const char Device::kIPFlagReversePathFilterEnabled[] = "1";
+// static
+const char Device::kIPFlagReversePathFilterLooseMode[] = "2";
// static
const char Device::kStoragePowered[] = "Powered";
@@ -214,6 +220,18 @@
kIPFlagUseTempAddrUsedAndDefault);
}
+void Device::DisableReversePathFilter() {
+ // TODO(pstew): Current kernel doesn't offer reverse-path filtering flag
+ // for IPv6. crosbug.com/24228
+ SetIPFlag(IPAddress::kFamilyIPv4, kIPFlagReversePathFilter,
+ kIPFlagReversePathFilterLooseMode);
+}
+
+void Device::EnableReversePathFilter() {
+ SetIPFlag(IPAddress::kFamilyIPv4, kIPFlagReversePathFilter,
+ kIPFlagReversePathFilterEnabled);
+}
+
bool Device::IsConnected() const {
if (selected_service_)
return selected_service_->IsConnected();
@@ -328,10 +346,10 @@
void Device::DestroyConnection() {
VLOG(2) << __func__;
- connection_ = NULL;
if (selected_service_.get()) {
selected_service_->SetConnection(NULL);
}
+ connection_ = NULL;
}
void Device::SelectService(const ServiceRefPtr &service) {
diff --git a/device.h b/device.h
index c10d6d0..85bf29b 100644
--- a/device.h
+++ b/device.h
@@ -79,6 +79,14 @@
virtual void EnableIPv6();
virtual void EnableIPv6Privacy();
+ // Request the removal of reverse-path filtering for this interface.
+ // This will allow packets destined for this interface to be accepted,
+ // even if this is not the default route for such a packet to arrive.
+ virtual void DisableReversePathFilter();
+
+ // Request reverse-path filtering for this interface.
+ virtual void EnableReversePathFilter();
+
// Returns true if the selected service on the device (if any) is connected.
// Returns false if there is no selected service, or if the selected service
// is not connected.
@@ -181,6 +189,9 @@
static const char kIPFlagDisableIPv6[];
static const char kIPFlagUseTempAddr[];
static const char kIPFlagUseTempAddrUsedAndDefault[];
+ static const char kIPFlagReversePathFilter[];
+ static const char kIPFlagReversePathFilterEnabled[];
+ static const char kIPFlagReversePathFilterLooseMode[];
static const char kStoragePowered[];
static const char kStorageIPConfigs[];
diff --git a/device_info.h b/device_info.h
index 1632951..6303e52 100644
--- a/device_info.h
+++ b/device_info.h
@@ -53,7 +53,7 @@
// messages, and registers it with the manager.
void RegisterDevice(const DeviceRefPtr &device);
- DeviceRefPtr GetDevice(int interface_index) const;
+ virtual DeviceRefPtr GetDevice(int interface_index) const;
virtual bool GetMACAddress(int interface_index, ByteString *address) const;
virtual bool GetFlags(int interface_index, unsigned int *flags) const;
virtual bool GetAddresses(int interface_index,
diff --git a/http_proxy.cc b/http_proxy.cc
index 60bc281..1ba1d21 100644
--- a/http_proxy.cc
+++ b/http_proxy.cc
@@ -20,6 +20,7 @@
#include <base/stringprintf.h>
#include "shill/async_connection.h"
+#include "shill/connection.h"
#include "shill/dns_client.h"
#include "shill/event_dispatcher.h"
#include "shill/ip_address.h"
@@ -46,12 +47,9 @@
const char HTTPProxy::kHTTPVersionPrefix[] = " HTTP/1";
const char HTTPProxy::kInternalErrorMsg[] = "Proxy Failed: Internal Error";
-
-HTTPProxy::HTTPProxy(const std::string &interface_name,
- const std::vector<std::string> &dns_servers)
+HTTPProxy::HTTPProxy(ConnectionRefPtr connection)
: state_(kStateIdle),
- interface_name_(interface_name),
- dns_servers_(dns_servers),
+ connection_(connection),
accept_callback_(NewCallback(this, &HTTPProxy::AcceptClient)),
connect_completion_callback_(
NewCallback(this, &HTTPProxy::OnConnectCompletion)),
@@ -70,6 +68,7 @@
client_socket_(-1),
server_port_(kDefaultServerPort),
server_socket_(-1),
+ is_route_requested_(false),
idle_timeout_(NULL) { }
HTTPProxy::~HTTPProxy() {
@@ -115,14 +114,14 @@
accept_callback_.get()));
dispatcher_ = dispatcher;
dns_client_.reset(new DNSClient(IPAddress::kFamilyIPv4,
- interface_name_,
- dns_servers_,
+ connection_->interface_name(),
+ connection_->dns_servers(),
kDNSTimeoutSeconds * 1000,
dispatcher,
dns_client_callback_.get()));
proxy_port_ = ntohs(addr.sin_port);
server_async_connection_.reset(
- new AsyncConnection(interface_name_, dispatcher, sockets,
+ new AsyncConnection(connection_->interface_name(), dispatcher, sockets,
connect_completion_callback_.get()));
sockets_ = sockets;
state_ = kStateWaitConnection;
@@ -280,6 +279,9 @@
server_hostname_ = host;
}
+ connection_->RequestRouting();
+ is_route_requested_ = true;
+
IPAddress addr(IPAddress::kFamilyIPv4);
if (addr.SetAddressFromString(server_hostname_)) {
if (!ConnectServer(addr, server_port_)) {
@@ -574,6 +576,10 @@
void HTTPProxy::StopClient() {
VLOG(3) << "In " << __func__;
+ if (is_route_requested_) {
+ connection_->ReleaseRouting();
+ is_route_requested_ = false;
+ }
write_client_handler_.reset();
read_client_handler_.reset();
if (client_socket_ != -1) {
diff --git a/http_proxy.h b/http_proxy.h
index 6bc0601..3b9c334 100644
--- a/http_proxy.h
+++ b/http_proxy.h
@@ -50,8 +50,7 @@
kStateFlushResponse,
};
- HTTPProxy(const std::string &interface_name,
- const std::vector<std::string> &dns_servers);
+ explicit HTTPProxy(ConnectionRefPtr connection);
virtual ~HTTPProxy();
// Start HTTP proxy.
@@ -111,8 +110,7 @@
// State held for the lifetime of the proxy.
State state_;
- const std::string interface_name_;
- std::vector<std::string> dns_servers_;
+ ConnectionRefPtr connection_;
scoped_ptr<Callback1<int>::Type> accept_callback_;
scoped_ptr<Callback2<bool, int>::Type> connect_completion_callback_;
scoped_ptr<Callback1<bool>::Type> dns_client_callback_;
@@ -136,6 +134,7 @@
std::string client_version_;
int server_port_;
int server_socket_;
+ bool is_route_requested_;
CancelableTask *idle_timeout_;
std::vector<std::string> client_headers_;
std::string server_hostname_;
diff --git a/http_proxy_unittest.cc b/http_proxy_unittest.cc
index 07e9cb7..d7f4ddb 100644
--- a/http_proxy_unittest.cc
+++ b/http_proxy_unittest.cc
@@ -14,6 +14,9 @@
#include "shill/ip_address.h"
#include "shill/mock_async_connection.h"
+#include "shill/mock_connection.h"
+#include "shill/mock_control.h"
+#include "shill/mock_device_info.h"
#include "shill/mock_dns_client.h"
#include "shill/mock_event_dispatcher.h"
#include "shill/mock_sockets.h"
@@ -25,6 +28,7 @@
using ::testing::AtLeast;
using ::testing::DoAll;
using ::testing::Invoke;
+using ::testing::NiceMock;
using ::testing::Return;
using ::testing::ReturnArg;
using ::testing::ReturnNew;
@@ -82,11 +86,23 @@
class HTTPProxyTest : public Test {
public:
HTTPProxyTest()
- : server_async_connection_(NULL),
+ : interface_name_(kInterfaceName),
+ server_async_connection_(NULL),
dns_servers_(kDNSServers, kDNSServers + 2),
dns_client_(NULL),
- proxy_(kInterfaceName, dns_servers_) { }
+ device_info_(new NiceMock<MockDeviceInfo>(
+ &control_,
+ reinterpret_cast<EventDispatcher*>(NULL),
+ reinterpret_cast<Manager*>(NULL))),
+ connection_(new StrictMock<MockConnection>(device_info_.get())),
+ proxy_(connection_) { }
protected:
+ virtual void SetUp() {
+ EXPECT_CALL(*connection_.get(), interface_name())
+ .WillRepeatedly(ReturnRef(interface_name_));
+ EXPECT_CALL(*connection_.get(), dns_servers())
+ .WillRepeatedly(ReturnRef(dns_servers_));
+ }
virtual void TearDown() {
if (proxy_.sockets_) {
ExpectStop();
@@ -152,9 +168,11 @@
EXPECT_FALSE(proxy_.write_client_handler_.get());
EXPECT_FALSE(proxy_.read_server_handler_.get());
EXPECT_FALSE(proxy_.write_server_handler_.get());
+ EXPECT_FALSE(proxy_.is_route_requested_);
}
void ExpectReset() {
EXPECT_FALSE(proxy_.accept_handler_.get());
+ EXPECT_EQ(proxy_.connection_.get(), connection_.get());
EXPECT_FALSE(proxy_.dispatcher_);
EXPECT_FALSE(proxy_.dns_client_.get());
EXPECT_EQ(-1, proxy_.proxy_port_);
@@ -189,6 +207,9 @@
EXPECT_CALL(*server_async_connection_, Stop())
.Times(AtLeast(1));
}
+ if (proxy_.is_route_requested_) {
+ EXPECT_CALL(*connection_.get(), ReleaseRouting());
+ }
}
void ExpectClientInput(int fd) {
EXPECT_CALL(sockets(), Accept(kProxyFD, _, _))
@@ -291,7 +312,6 @@
.WillOnce(ReturnNew<IOHandler>());
ExpectRepeatedInputTimeout();
}
-
void ExpectTunnelClose() {
EXPECT_CALL(sockets(), Close(kClientFD))
.WillOnce(Return(0));
@@ -299,6 +319,12 @@
.WillOnce(Return(0));
ExpectStop();
}
+ void ExpectRouteRequest() {
+ EXPECT_CALL(*connection_.get(), RequestRouting());
+ }
+ void ExpectRouteRelease() {
+ EXPECT_CALL(*connection_.get(), ReleaseRouting());
+ }
// Callers for various private routines in the proxy
bool StartProxy() {
@@ -369,6 +395,7 @@
void SetupConnectWithRequest(const string &url, const string &http_version,
const string &extra_lines) {
ExpectDNSRequest("www.chromium.org", true);
+ ExpectRouteRequest();
ReadFromClient(CreateRequest(url, http_version, extra_lines));
IPAddress addr(IPAddress::kFamilyIPv4);
EXPECT_TRUE(addr.SetAddressFromString(kServerAddress));
@@ -393,12 +420,16 @@
}
private:
+ const string interface_name_;
// Owned by the HTTPProxy, but tracked here for EXPECT().
StrictMock<MockAsyncConnection> *server_async_connection_;
vector<string> dns_servers_;
// Owned by the HTTPProxy, but tracked here for EXPECT().
StrictMock<MockDNSClient> *dns_client_;
MockEventDispatcher dispatcher_;
+ MockControl control_;
+ scoped_ptr<MockDeviceInfo> device_info_;
+ scoped_refptr<MockConnection> connection_;
HTTPProxy proxy_;
StrictMock<MockSockets> sockets_;
};
@@ -553,6 +584,7 @@
TEST_F(HTTPProxyTest, DNSRequestFailure) {
SetupClient();
+ ExpectRouteRequest();
ExpectDNSRequest("www.chromium.org", false);
ExpectClientResult();
ReadFromClient(CreateRequest("/", "1.1", "Host: www.chromium.org:40506"));
@@ -561,6 +593,7 @@
TEST_F(HTTPProxyTest, DNSRequestDelayedFailure) {
SetupClient();
+ ExpectRouteRequest();
ExpectDNSRequest("www.chromium.org", true);
ReadFromClient(CreateRequest("/", "1.1", "Host: www.chromium.org:40506"));
ExpectClientResult();
@@ -573,6 +606,7 @@
TEST_F(HTTPProxyTest, TrailingClientData) {
SetupClient();
+ ExpectRouteRequest();
ExpectDNSRequest("www.chromium.org", true);
const string trailing_data("Trailing client data");
ReadFromClient(CreateRequest("/", "1.1", "Host: www.chromium.org:40506") +
@@ -584,6 +618,7 @@
TEST_F(HTTPProxyTest, LineContinuation) {
SetupClient();
+ ExpectRouteRequest();
ExpectDNSRequest("www.chromium.org", true);
string text_to_keep("X-Long-Header: this is one line\r\n"
"\tand this is another");
@@ -598,6 +633,7 @@
// continuation.
TEST_F(HTTPProxyTest, LineContinuationRemoval) {
SetupClient();
+ ExpectRouteRequest();
ExpectDNSRequest("www.chromium.org", true);
string text_to_remove("remove this text please");
ReadFromClient(CreateRequest("http://www.chromium.org/", "1.1",
@@ -634,6 +670,7 @@
SetupClient();
ExpectSyncConnect(kServerAddress, 999);
ExpectRepeatedServerOutput();
+ ExpectRouteRequest();
ReadFromClient(CreateRequest("/", "1.1",
StringPrintf("Host: %s:999", kServerAddress)));
EXPECT_EQ(HTTPProxy::kStateTunnelData, GetProxyState());
@@ -730,6 +767,7 @@
.WillOnce(Return(0));
EXPECT_CALL(sockets(), Close(kServerFD))
.WillOnce(Return(0));
+ ExpectRouteRelease();
StopClient();
ExpectClientReset();
EXPECT_EQ(HTTPProxy::kStateWaitConnection, GetProxyState());
diff --git a/mock_connection.h b/mock_connection.h
index 06f067f..2d8af12 100644
--- a/mock_connection.h
+++ b/mock_connection.h
@@ -19,6 +19,10 @@
MOCK_METHOD1(UpdateFromIPConfig, void(const IPConfigRefPtr &config));
MOCK_METHOD1(SetIsDefault, void(bool is_default));
+ MOCK_METHOD0(RequestRouting, void());
+ MOCK_METHOD0(ReleaseRouting, void());
+ MOCK_CONST_METHOD0(interface_name, const std::string &());
+ MOCK_CONST_METHOD0(dns_servers, const std::vector<std::string> &());
private:
DISALLOW_COPY_AND_ASSIGN(MockConnection);
diff --git a/mock_device.h b/mock_device.h
index 462bc21..de0c7b7 100644
--- a/mock_device.h
+++ b/mock_device.h
@@ -34,6 +34,8 @@
MOCK_METHOD0(DisableIPv6, void());
MOCK_METHOD0(EnableIPv6, void());
MOCK_METHOD0(EnableIPv6Privacy, void());
+ MOCK_METHOD0(DisableReversePathFilter, void());
+ MOCK_METHOD0(EnableReversePathFilter, void());
MOCK_CONST_METHOD0(technology, Technology::Identifier());
private:
diff --git a/mock_device_info.h b/mock_device_info.h
index 5808f50..b630505 100644
--- a/mock_device_info.h
+++ b/mock_device_info.h
@@ -26,6 +26,7 @@
Manager *manager);
virtual ~MockDeviceInfo();
+ MOCK_CONST_METHOD1(GetDevice, DeviceRefPtr(int interface_index));
MOCK_CONST_METHOD2(GetMACAddress, bool(int interface_index,
ByteString* address));
MOCK_CONST_METHOD2(GetFlags, bool(int interface_index,
diff --git a/mock_routing_table.h b/mock_routing_table.h
index 1afd37e..9eaa870 100644
--- a/mock_routing_table.h
+++ b/mock_routing_table.h
@@ -28,6 +28,7 @@
const IPConfigRefPtr &ipconfig,
uint32 metric));
MOCK_METHOD1(FlushRoutes, void(int interface_index));
+ MOCK_METHOD0(FlushCache, bool());
MOCK_METHOD1(ResetTable, void(int interface_index));
MOCK_METHOD2(SetDefaultMetric, void(int interface_index, uint32 metric));
diff --git a/modem_unittest.cc b/modem_unittest.cc
index ed19523..00646ca 100644
--- a/modem_unittest.cc
+++ b/modem_unittest.cc
@@ -164,6 +164,8 @@
EXPECT_CALL(info_, GetMACAddress(kTestInterfaceIndex, _))
.WillOnce(DoAll(SetArgumentPointee<1>(expected_address), Return(true)))
.WillOnce(DoAll(SetArgumentPointee<1>(expected_address), Return(true)));
+ EXPECT_CALL(info_, GetDevice(kTestInterfaceIndex))
+ .WillRepeatedly(Return(modem_.device_));
EXPECT_CALL(manager_, device_info()).WillRepeatedly(Return(&info_));
modem_.CreateCellularDevice(props);
diff --git a/routing_table.h b/routing_table.h
index 08a0fa9..cf31f1c 100644
--- a/routing_table.h
+++ b/routing_table.h
@@ -36,10 +36,10 @@
virtual void Start();
virtual void Stop();
- // Add an entry to the routing table
+ // Add an entry to the routing table.
virtual bool AddRoute(int interface_index, const RoutingTableEntry &entry);
- // Get the default route associated with an interface of a given addr family
+ // Get the default route associated with an interface of a given addr family.
virtual bool GetDefaultRoute(int interface_index,
IPAddress::Family family,
RoutingTableEntry *entry);
@@ -49,13 +49,16 @@
const IPConfigRefPtr &ipconfig,
uint32 metric);
- // Remove all routes associated with interface
+ // Remove all routes associated with interface.
virtual void FlushRoutes(int interface_index);
- // Reset local state for this interface
+ // Flush the routing cache for all interfaces.
+ virtual bool FlushCache();
+
+ // Reset local state for this interface.
virtual void ResetTable(int interface_index);
- // Set the metric (priority) on existing default routes for an interface
+ // Set the metric (priority) on existing default routes for an interface.
virtual void SetDefaultMetric(int interface_index, uint32 metric);
protected:
@@ -73,13 +76,12 @@
void ReplaceMetric(uint32 interface_index,
const RoutingTableEntry &entry,
uint32 metric);
- bool FlushCache();
static const char kRouteFlushPath4[];
static const char kRouteFlushPath6[];
base::hash_map<int, std::vector<RoutingTableEntry> > tables_; // NOLINT
- // NOLINT above: hash_map from base, no need to #include <hash_map>
+ // NOLINT above: hash_map from base, no need to #include <hash_map>.
scoped_ptr<Callback1<const RTNLMessage &>::Type> route_callback_;
scoped_ptr<RTNLListener> route_listener_;
diff --git a/service.cc b/service.cc
index a0f3347..65a5828 100644
--- a/service.cc
+++ b/service.cc
@@ -320,8 +320,7 @@
void Service::SetConnection(ConnectionRefPtr connection) {
if (connection.get()) {
- http_proxy_.reset(new HTTPProxy(connection->interface_name(),
- connection->dns_servers()));
+ http_proxy_.reset(new HTTPProxy(connection));
http_proxy_->Start(dispatcher_, &sockets_);
} else {
http_proxy_.reset();