shill: support 3G dongles with PPP interface

Assuming the 3G dongle has been switched to modem mode (with
usb_modeswitch or similar), and an activated SIM is present,
shill will automatically connect to the cellular network.

The primary change, as far as the Cellular/Modem logic goes,
is that we take the absence of a link name to mean that the
modem is a PPP dongle. Instead of bailing out, we create the
Cellular object, and register it with the manager as any other
Cellular device.

When the Cellular connection is complete, CellularCapabilityUniversal
checks the Bearer's IPConfig method, as indicated by modemmanager1.
If the method is specified as PPP, the capability asks the Cellular
device to start PPP.

When PPP setup completes, Cellular passes the IP configuration
information to the PPPDevice. At that point, the PPPDevice is
assigned an IP address, and routing is updated appropriately.

Notable changes:
- Moved VPN to VirtualDevice, changed OpenVPNDriver to use it,
  created a new subclass PPPDevice.
- Moved PPP code out of L2TPIPSecDriver, and into PPPDevice.
- Changed L2TPIPSecDriver to use PPPDevice.

While there:
- Got rid of VPNDriver::OnDisconnected, and changed callers to
  use DropConnection instead.
- Made Load and Save of VirtualDevices no-ops. This eliminates
  the confusingly named "device_" stanzas in the default profile.
  We lose VPN byte counts by doing this, but they weren't sensible
  anyway (they'd be shared across potentially different VPNs).

New units will follow in another CL (TBW).

BUG=chromium:240051
TEST=unit tests, manual

Manual testing
--------------
1. Get 3G PPP dongle.
2. Install activated SIM.
3. Plug dongle into USB port.
4. Wait for the dongle to switch to modem mode.
   (I used a manually installed usb_modeswitch, but this will
   soon be handled by mist.)
5. Wait for the dongle to connect. With the Huawei E303, this
   takes about 35 seconds.

Change-Id: I916bef451ee6e8dcf1af8135ecf6787251acf19b
Reviewed-on: https://gerrit.chromium.org/gerrit/51356
Commit-Queue: mukesh agrawal <quiche@chromium.org>
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Tested-by: mukesh agrawal <quiche@chromium.org>
diff --git a/ppp_device.h b/ppp_device.h
new file mode 100644
index 0000000..becc484
--- /dev/null
+++ b/ppp_device.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SHILL_PPP_DEVICE_H_
+#define SHILL_PPP_DEVICE_H_
+
+#include <base/basictypes.h>
+
+#include <map>
+#include <string>
+
+#include "shill/ipconfig.h"
+#include "shill/virtual_device.h"
+
+namespace shill {
+
+// Declared in the header to avoid linking unused code into shims.
+static const char kPPPDNS1[] = "DNS1";
+static const char kPPPDNS2[] = "DNS2";
+static const char kPPPExternalIP4Address[] = "EXTERNAL_IP4_ADDRESS";
+static const char kPPPGatewayAddress[] = "GATEWAY_ADDRESS";
+static const char kPPPInterfaceName[] = "INTERNAL_IFNAME";
+static const char kPPPInternalIP4Address[] = "INTERNAL_IP4_ADDRESS";
+static const char kPPPLNSAddress[] = "LNS_ADDRESS";
+static const char kPPPReasonConnect[] = "connect";
+static const char kPPPReasonDisconnect[] = "disconnect";
+
+class PPPDevice : public VirtualDevice {
+ public:
+  static const char kDaemonPath[];
+  static const char kPluginPath[];
+
+  PPPDevice(ControlInterface *control,
+            EventDispatcher *dispatcher,
+            Metrics *metrics,
+            Manager *manager,
+            const std::string &link_name,
+            int interface_index);
+  virtual ~PPPDevice();
+
+  // Set IPConfig for this device, based on the dictionary of
+  // configuration strings received from our PPP plugin.
+  virtual void UpdateIPConfigFromPPP(
+      const std::map<std::string, std::string> &configuration,
+      bool blackhole_ipv6);
+
+  // Get the network device name (e.g. "ppp0") from the dictionary of
+  // configuration strings received from our PPP plugin.
+  static std::string GetInterfaceName(
+      const std::map<std::string, std::string> &configuration);
+
+ private:
+  FRIEND_TEST(PPPDeviceTest, GetInterfaceName);
+  FRIEND_TEST(PPPDeviceTest, ParseIPConfiguration);
+
+  static void ParseIPConfiguration(
+      const std::string &link_name,
+      const std::map<std::string, std::string> &configuration,
+      IPConfig::Properties *properties);
+
+  DISALLOW_COPY_AND_ASSIGN(PPPDevice);
+};
+
+}  // namespace shill
+
+#endif  // SHILL_PPP_DEVICE_H_