shill: Pass a parameter to dhcp client to request a hostname

This will enable dynamic DNS, or at the very least allow DHCP
requests to be identified and distinguished at the server side.

BUG=chromium-os:23741
TEST=New unit tests monitor hostname arg passed to dhcpcd,
and to assure values are being loaded/saved.  Also double
checked on real system by doing a dbus-send to set manager.HostName
and checked that the name was persisted, and that the next
DHCP server we connected to stored this hostname.
CQ-DEPEND=Ic807a2235e0cdcb32a08f9c2c760a86c3579431c

Change-Id: Ic127b65d8563b15e55549a0f029385d0632eaf6c
Reviewed-on: https://gerrit.chromium.org/gerrit/14045
Reviewed-by: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
Commit-Ready: Paul Stewart <pstew@chromium.org>
diff --git a/dhcp_config_unittest.cc b/dhcp_config_unittest.cc
index 9a89c90..0a19e54 100644
--- a/dhcp_config_unittest.cc
+++ b/dhcp_config_unittest.cc
@@ -30,6 +30,7 @@
 
 namespace {
 const char kDeviceName[] = "eth0";
+const char kHostName[] = "hostname";
 }  // namespace {}
 
 class DHCPConfigTest : public PropertyStoreTest {
@@ -41,6 +42,7 @@
                                dispatcher(),
                                DHCPProvider::GetInstance(),
                                kDeviceName,
+                               kHostName,
                                glib())) {}
 
   virtual void SetUp() {
@@ -152,6 +154,47 @@
   EXPECT_EQ(0, config_->pid_);
 }
 
+MATCHER_P(IsDHCPCDArgs, has_hostname, "") {
+  if (string(arg[0]) != "/sbin/dhcpcd" ||
+      string(arg[1]) != "-B" ||
+      string(arg[2]) != kDeviceName) {
+    return false;
+  }
+
+  if (has_hostname) {
+    if (string(arg[3]) != "-h" ||
+        string(arg[4]) != kHostName ||
+        arg[5] != NULL) {
+      return false;
+    }
+  } else {
+      if (arg[3] != NULL) {
+        return false;
+      }
+  }
+
+  return true;
+}
+
+TEST_F(DHCPConfigTest, StartWithHostname) {
+  EXPECT_CALL(*glib(), SpawnAsync(_, IsDHCPCDArgs(true), _, _, _, _, _, _))
+      .WillOnce(Return(false));
+  EXPECT_FALSE(config_->Start());
+}
+
+TEST_F(DHCPConfigTest, StartWithoutHostname) {
+  DHCPConfigRefPtr config(new DHCPConfig(&control_,
+                                         dispatcher(),
+                                         DHCPProvider::GetInstance(),
+                                         kDeviceName,
+                                         "",
+                                         glib()));
+
+  EXPECT_CALL(*glib(), SpawnAsync(_, IsDHCPCDArgs(false), _, _, _, _, _, _))
+      .WillOnce(Return(false));
+  EXPECT_FALSE(config->Start());
+}
+
 namespace {
 
 class UpdateCallbackTest {