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/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) {