dhcp client: add Serialize() to class DHCPMessage
Add the funtion Serialize() to class DHCPMessage.
This allows us to convert a DHCPMessage object to a
serialized message.
Bug: 25642025
TEST=compile and unittest
Change-Id: Ia291d1b83a8b6d8c48501172dbc08b3776cb986e
diff --git a/dhcp_message.cc b/dhcp_message.cc
index 474018e..f0a84c6 100644
--- a/dhcp_message.cc
+++ b/dhcp_message.cc
@@ -28,6 +28,7 @@
#include <base/logging.h>
#include "dhcp_client/dhcp_options.h"
+#include "dhcp_client/dhcp_options_writer.h"
using shill::ByteString;
@@ -66,6 +67,8 @@
DHCPMessage::DHCPMessage()
: lease_time_(0),
+ message_type_(0),
+ server_identifier_(0),
renewal_time_(0),
rebinding_time_(0) {
options_map_.insert(std::make_pair(kDHCPOptionMessageType,
@@ -255,6 +258,74 @@
return true;
}
+bool DHCPMessage::Serialize(ByteString* data) {
+ RawDHCPMessage raw_message;
+ raw_message.op = opcode_;
+ raw_message.htype = hardware_address_type_;
+ raw_message.hlen = hardware_address_length_;
+ raw_message.hops = relay_hops_;
+ raw_message.xid = htonl(transaction_id_);
+ raw_message.secs = htons(seconds_);
+ raw_message.flags = htons(flags_);
+ raw_message.ciaddr = htonl(client_ip_address_);
+ raw_message.yiaddr = htonl(your_ip_address_);
+ raw_message.siaddr = htonl(next_server_ip_address_);
+ raw_message.giaddr = htonl(agent_ip_address_);
+ raw_message.cookie = htonl(cookie_);
+ memcpy(raw_message.chaddr,
+ client_hardware_address_.GetConstData(),
+ hardware_address_length_);
+ if (servername_.length() >= kServerNameLength) {
+ LOG(ERROR) << "Invalid server name length: " << servername_.length();
+ return false;
+ }
+ memcpy(raw_message.sname,
+ servername_.c_str(),
+ servername_.length());
+ raw_message.sname[servername_.length()] = 0;
+ if (bootfile_.length() >= kBootFileLength) {
+ LOG(ERROR) << "Invalid boot file length: " << bootfile_.length();
+ return false;
+ }
+ memcpy(raw_message.file,
+ bootfile_.c_str(),
+ bootfile_.length());
+ raw_message.file[bootfile_.length()] = 0;
+ data->Append(ByteString(reinterpret_cast<const char*>(&raw_message),
+ sizeof(raw_message) - kDHCPOptionLength));
+ // Append DHCP options to the message.
+ DHCPOptionsWriter* options_writer = DHCPOptionsWriter::GetInstance();
+ if (options_writer->WriteUInt8Option(data,
+ kDHCPOptionMessageType,
+ message_type_) == -1) {
+ LOG(ERROR) << "Failed to write message type option";
+ return false;
+ }
+ if (lease_time_ != 0) {
+ if (options_writer->WriteUInt32Option(data,
+ kDHCPOptionLeaseTime,
+ lease_time_) == -1) {
+ LOG(ERROR) << "Failed to write lease time option";
+ return false;
+ }
+ }
+ if (server_identifier_ != 0) {
+ if (options_writer->WriteUInt32Option(data,
+ kDHCPOptionServerIdentifier,
+ server_identifier_) == -1) {
+ LOG(ERROR) << "Failed to write server identifier option";
+ return false;
+ }
+ }
+ // TODO(nywang): Append other options.
+ // Append end tag.
+ if (options_writer->WriteEndTag(data) == -1) {
+ LOG(ERROR) << "Failed to write DHCP options end tag";
+ return false;
+ }
+ return true;
+}
+
uint16_t DHCPMessage::ComputeChecksum(const uint8_t* data, size_t len) {
uint32_t sum = 0;
diff --git a/dhcp_message.h b/dhcp_message.h
index a839ee1..235b377 100644
--- a/dhcp_message.h
+++ b/dhcp_message.h
@@ -58,6 +58,8 @@
DHCPMessage* message);
static uint16_t ComputeChecksum(const uint8_t* data, size_t len);
+ bool Serialize(shill::ByteString* data);
+
uint8_t message_type() const {return message_type_;}
uint32_t lease_time() const {return lease_time_;}