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