DHCPMessaget: support DHCP option 'message'

This adds the support for DHCP option 'message'.
This allows both the client and server to indicate the
reason of failure using a string.

While there, this also fixes a few typos.
Bug: 25642025
TEST=compile and unittest

Change-Id: Ie678923c14ccbaea8e4801418c919c07108cfded
diff --git a/dhcp_message.cc b/dhcp_message.cc
index 1fc2dd3..c19b25d 100644
--- a/dhcp_message.cc
+++ b/dhcp_message.cc
@@ -76,6 +76,8 @@
       ParserContext(new UInt8Parser(), &message_type_)));
   options_map_.insert(std::make_pair(kDHCPOptionLeaseTime,
       ParserContext(new UInt32Parser(), &lease_time_)));
+  options_map_.insert(std::make_pair(kDHCPOptionMessage,
+      ParserContext(new StringParser(), &error_message_)));
   options_map_.insert(std::make_pair(kDHCPOptionSubnetMask,
       ParserContext(new UInt32Parser(), &subnet_mask_)));
   options_map_.insert(std::make_pair(kDHCPOptionServerIdentifier,
@@ -325,6 +327,14 @@
       return false;
     }
   }
+  if (error_message_.size() != 0) {
+    if (options_writer->WriteStringOption(data,
+                                          kDHCPOptionMessage,
+                                          error_message_) == -1) {
+      LOG(ERROR) << "Failed to write error message option";
+      return false;
+    }
+  }
   if (parameter_request_list_.size() != 0) {
     if (options_writer->WriteUInt8ListOption(data,
                                              kDHCPOptionParameterRequestList,
@@ -384,6 +394,10 @@
   client_hardware_address_ = client_hardware_address;
 }
 
+void DHCPMessage::SetErrorMessage(const std::string& error_message) {
+  error_message_ = error_message;
+}
+
 void DHCPMessage::SetLeaseTime(uint32_t lease_time) {
   lease_time_ = lease_time;
 }
diff --git a/dhcp_message.h b/dhcp_message.h
index 3fc5bca..f104406 100644
--- a/dhcp_message.h
+++ b/dhcp_message.h
@@ -65,11 +65,12 @@
   // Serialize the message to a buffer
   bool Serialize(shill::ByteString* data);
 
-  // DHCP option and filed setters
+  // DHCP option and field setters
   void SetClientHardwareAddress(
       const shill::ByteString& client_hardware_address);
   void SetClientIdentifier(const shill::ByteString& client_identifier);
   void SetClientIPAddress(uint32_t client_ip_address);
+  void SetErrorMessage(const std::string& error_message);
   void SetLeaseTime(uint32_t lease_time);
   void SetMessageType(uint8_t message_type);
   void SetParameterRequestList(
@@ -77,7 +78,7 @@
   void SetServerIdentifier(uint32_t server_identifier);
   void SetTransactionID(uint32_t transaction_id);
 
-  // DHCP option and filed getters
+  // DHCP option and field getters
   const shill::ByteString& client_hardware_address() const {
     return client_hardware_address_;
   }
@@ -85,8 +86,8 @@
     return client_identifier_;
   }
   uint32_t client_ip_address() const { return client_ip_address_; }
-  std::string domain_name() const { return domain_name_; }
-
+  const std::string& domain_name() const { return domain_name_; }
+  const std::string& error_message() const { return error_message_; }
   uint32_t lease_time() const { return lease_time_; }
   uint8_t message_type() const { return message_type_; }
   uint32_t rebinding_time() const { return rebinding_time_; }
@@ -157,6 +158,8 @@
   uint32_t server_identifier_;
   // Option 55: Parameter Request List.
   std::vector<uint8_t> parameter_request_list_;
+  // Option 56: (Error) Message.
+  std::string error_message_;
   // Option 58: Renewal time value in unit of seconds.
   uint32_t renewal_time_;
   // Option 59: Rebinding time value in unit of seconds.
diff --git a/dhcp_options.h b/dhcp_options.h
index 1a9f498..8257585 100644
--- a/dhcp_options.h
+++ b/dhcp_options.h
@@ -28,6 +28,7 @@
 const uint8_t kDHCPOptionMessageType = 53;
 const uint8_t kDHCPOptionServerIdentifier = 54;
 const uint8_t kDHCPOptionParameterRequestList = 55;
+const uint8_t kDHCPOptionMessage = 56;
 const uint8_t kDHCPOptionRenewalTime = 58;
 const uint8_t kDHCPOptionRebindingTime = 59;
 const uint8_t kDHCPOptionClientIdentifier = 61;