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/device_info.cc b/device_info.cc
index 75f4734..31d6c39 100644
--- a/device_info.cc
+++ b/device_info.cc
@@ -265,7 +265,13 @@
         // Tunnel devices are managed by the VPN code.
         VLOG(2) << "Tunnel link " << link_name << " at index " << dev_index
                 << " -- notifying VPNProvider.";
-        // TODO(pstew): Notify VPNProvider once that method exists.
+        if (manager_->vpn_provider()->OnDeviceInfoAvailable(link_name,
+                                                             dev_index)) {
+          // VPN does not know anything about this tunnel, it is probably
+          // left over from a previous instance and should not exist.
+          VLOG(2) << "Tunnel link is unused.  Deleting.";
+          DeleteInterface(dev_index);
+        }
         return;
       default:
         device = new DeviceStub(control_interface_, dispatcher_, metrics_,
@@ -342,7 +348,7 @@
   return true;
 }
 
-bool DeviceInfo::CreateTunnelInterface(string *interface_name) {
+bool DeviceInfo::CreateTunnelInterface(string *interface_name) const {
   int fd = HANDLE_EINTR(open(kTunDeviceName, O_RDWR));
   if (fd < 0) {
     PLOG(ERROR) << "failed to open " << kTunDeviceName;
@@ -368,7 +374,7 @@
   return true;
 }
 
-bool DeviceInfo::DeleteInterface(int interface_index) {
+bool DeviceInfo::DeleteInterface(int interface_index) const {
   return rtnl_handler_->RemoveInterface(interface_index);
 }