shill: vpn: Claim interface from DeviceInfo

Maintain a list in the VPNProvider of all services created by it.
When DeviceInfo alerts it of a new tunnel interface, VPNProvider
will find a service->driver() to accept this interface.  If not
found, delete the interface (cleaning up after crash).  Also,
in OpenVPNDriver, create a tunnel device and hold enough state
to be able to claim it later.

BUG=chromium-os:26841,chromium-os:27156,chromium-os:27158
TEST=New unit tests.  Manual: Ensure tunnel devices get cleaned up on a
real system.

Change-Id: Iaaa44dc26830a2e8bf5dfea00d165ab8c034e6e9
Reviewed-on: https://gerrit.chromium.org/gerrit/17191
Reviewed-by: Darin Petkov <petkov@chromium.org>
Commit-Ready: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/vpn_provider.cc b/vpn_provider.cc
index 84903f7..0adffcb 100644
--- a/vpn_provider.cc
+++ b/vpn_provider.cc
@@ -8,10 +8,12 @@
 #include <chromeos/dbus/service_constants.h>
 
 #include "shill/error.h"
+#include "shill/manager.h"
 #include "shill/openvpn_driver.h"
 #include "shill/vpn_service.h"
 
 using std::string;
+using std::vector;
 
 namespace shill {
 
@@ -38,17 +40,38 @@
         error, Error::kNotSupported, "Missing VPN type property.");
     return NULL;
   }
+
   const string &type = args.GetString(flimflam::kProviderTypeProperty);
   scoped_ptr<VPNDriver> driver;
   if (type == flimflam::kProviderOpenVpn) {
-    driver.reset(new OpenVPNDriver(control_interface_, args));
+    driver.reset(new OpenVPNDriver(control_interface_,
+                                   manager_->device_info(), args));
   } else {
     Error::PopulateAndLog(
         error, Error::kNotSupported, "Unsupported VPN type: " + type);
     return NULL;
   }
-  return new VPNService(
-      control_interface_, dispatcher_, metrics_, manager_, driver.release());
+
+  services_.push_back(
+      new VPNService(
+          control_interface_, dispatcher_, metrics_, manager_,
+          driver.release()));
+
+  return services_.back();
+
+}
+
+bool VPNProvider::OnDeviceInfoAvailable(const string &link_name,
+                                        int interface_index) {
+  for (vector<VPNServiceRefPtr>::const_iterator it = services_.begin();
+       it != services_.end();
+       ++it) {
+    if ((*it)->driver()->ClaimInterface(link_name, interface_index)) {
+      return true;
+    }
+  }
+
+  return false;
 }
 
 }  // namespace shill