shill: Split Nl80211Message into class hierarchy.
Gotta apologize for this CL: it's a bit more gnarly than I'd like.
There're not that many modifications but, with all the moving of code,
it's harder to review than I'd like. I found that, easier than gerrit,
cherry-pick the change, do a git show HEAD^:nl80211_message.[ch] > old.[ch],
and edit the old and new files, together.
With the exception of the following changes, the Nl80211Message code was
just split into the NetlinkMessage <|-- GenericNetlinkMessage <|--
Nl80211Message class hierarchy.
1. In |NetlinkMessage::InitAndStripHeader|, a length check was
added to verify that enough bytes for the |nlmsghdr| exists.
2. In |GenericNetlinkMessage::Encode|, changed name of |attributes|
variable to |attribute_string|.
3. Split |EncodeHeader| and |InitAndStripHeader|, each, into
|nlmsghdr| and |genlmsghdr| pieces.
4. In |NetlinkMessage::EncodeHeader|, added encoding of |flags_| (that
had, somehow, gotten missed in the previous CL -- all other
|flags_| processing had been included.)
5. Removed the following unused methods from |Nl80211Message|:
- GetHeaderString
- StringFromFrame
- StringFromKeyType
- StringFromRegInitiator
- StringFromSsid
BUG=chromium-os:38221
TEST=unittest.
Change-Id: I208ede49fa8003d49eb487365f886a8f0d53da3f
Reviewed-on: https://gerrit.chromium.org/gerrit/44640
Reviewed-by: Christopher Wiley <wiley@chromium.org>
Reviewed-by: Wade Guthrie <wdg@chromium.org>
Tested-by: Wade Guthrie <wdg@chromium.org>
Commit-Queue: Wade Guthrie <wdg@chromium.org>
diff --git a/nl80211_message.cc b/nl80211_message.cc
index 60ea977..67dea40 100644
--- a/nl80211_message.cc
+++ b/nl80211_message.cc
@@ -73,9 +73,8 @@
const uint8_t Nl80211Frame::kMinimumFrameByteCount = 26;
const uint8_t Nl80211Frame::kFrameTypeMask = 0xfc;
-// TODO(wdg): These will go into NetlinkMessage when that class exists.
-const uint32_t Nl80211Message::kBroadcastSequenceNumber = 0;
-const uint16_t Nl80211Message::kIllegalMessageType = UINT16_MAX;
+const uint32_t NetlinkMessage::kBroadcastSequenceNumber = 0;
+const uint16_t NetlinkMessage::kIllegalMessageType = UINT16_MAX;
const char Nl80211Message::kBogusMacAddress[] = "XX:XX:XX:XX:XX:XX";
const unsigned int Nl80211Message::kEthernetAddressBytes = 6;
@@ -83,40 +82,43 @@
map<uint16_t, string> *Nl80211Message::status_code_string_ = NULL;
uint16_t Nl80211Message::nl80211_message_type_ = kIllegalMessageType;
+// NetlinkMessage
-// The nl messages look like this:
-//
-// XXXXXXXXXXXXXXXXXXX-nlmsg_total_size-XXXXXXXXXXXXXXXXXXX
-// XXXXXXXXXXXXXXXXXXX-nlmsg_msg_size-XXXXXXXXXXXXXXXXXXX
-// +-- gnhl nlmsg_tail(hdr) --+
-// | nlmsg_next(hdr) --+
-// v XXXXXXXXXXXX-nlmsg_len-XXXXXXXXXXXXXX V
-// -----+-----+-+----------------------------------------------+-++----
-// ... | | | payload | ||
-// | | +------+-+--------+-+--------------------------+ ||
-// | nl | | | | | | attribs | ||
-// | msg |p| genl |p| family |p+------+-+-------+-+-------+p|| ...
-// | hdr |a| msg |a| header |a| nl |p| pay |p| |a||
-// | |d| hdr |d| |d| attr |a| load |a| ... |d||
-// | | | | | | | |d| |d| | ||
-// -----+-----+-+----------------------------------------------+-++----
-// ^ ^ ^ ^
-// | | | XXXXXXX <-- nla_len(nlattr)
-// | | | +-- nla_data(nlattr)
-// | | X-nla_total_size-X
-// | | XXXXX-nlmsg_attrlen-XXXXXX
-// | +-- nlmsg_data(hdr) +-- nlmsg_attrdata()
-// +-- msg = nlmsg_hdr(raw_message)
+ByteString NetlinkMessage::EncodeHeader(uint32_t sequence_number,
+ uint16_t nlmsg_type) {
+ ByteString result;
+ sequence_number_ = sequence_number;
+ if (sequence_number_ == kBroadcastSequenceNumber) {
+ LOG(ERROR) << "Couldn't get a legal sequence number";
+ return result;
+ }
-//
-// Nl80211Message
-//
+ // Build netlink header.
+ nlmsghdr header;
+ size_t nlmsghdr_with_pad = NLMSG_ALIGN(sizeof(header));
+ header.nlmsg_len = nlmsghdr_with_pad;
+ header.nlmsg_type = nlmsg_type;
+ header.nlmsg_flags = NLM_F_REQUEST | flags_;
+ header.nlmsg_seq = sequence_number_;
+ header.nlmsg_pid = getpid();
-bool Nl80211Message::InitAndStripHeader(ByteString *input) {
+ // Netlink header + pad.
+ result.Append(ByteString(reinterpret_cast<unsigned char *>(&header),
+ sizeof(header)));
+ result.Resize(nlmsghdr_with_pad); // Zero-fill pad space (if any).
+ return result;
+}
+
+bool NetlinkMessage::InitAndStripHeader(ByteString *input) {
if (!input) {
LOG(ERROR) << "NULL input";
return false;
}
+ if (input->GetLength() < sizeof(nlmsghdr)) {
+ LOG(ERROR) << "Insufficient input to extract nlmsghdr";
+ return false;
+ }
+
// Read the nlmsghdr.
nlmsghdr *header = reinterpret_cast<nlmsghdr *>(input->GetData());
message_type_ = header->nlmsg_type;
@@ -125,6 +127,127 @@
// Strip the nlmsghdr.
input->RemovePrefix(NLMSG_ALIGN(sizeof(struct nlmsghdr)));
+ return true;
+}
+
+bool NetlinkMessage::InitFromNlmsg(const nlmsghdr *const_msg) {
+ if (!const_msg) {
+ LOG(ERROR) << "Null |const_msg| parameter";
+ return false;
+ }
+ ByteString message(reinterpret_cast<const unsigned char *>(const_msg),
+ const_msg->nlmsg_len);
+ if (!InitAndStripHeader(&message)) {
+ return false;
+ }
+ return true;
+}
+
+// static
+void NetlinkMessage::PrintBytes(int log_level, const unsigned char *buf,
+ size_t num_bytes) {
+ SLOG(WiFi, log_level) << "Netlink Message -- Examining Bytes";
+ if (!buf) {
+ SLOG(WiFi, log_level) << "<NULL Buffer>";
+ return;
+ }
+
+ if (num_bytes >= sizeof(nlmsghdr)) {
+ const nlmsghdr *header = reinterpret_cast<const nlmsghdr *>(buf);
+ SLOG(WiFi, log_level) << StringPrintf(
+ "len: %02x %02x %02x %02x = %u bytes",
+ buf[0], buf[1], buf[2], buf[3], header->nlmsg_len);
+
+ SLOG(WiFi, log_level) << StringPrintf(
+ "type | flags: %02x %02x %02x %02x - type:%u flags:%s%s%s%s%s",
+ buf[4], buf[5], buf[6], buf[7], header->nlmsg_type,
+ ((header->nlmsg_flags & NLM_F_REQUEST) ? " REQUEST" : ""),
+ ((header->nlmsg_flags & NLM_F_MULTI) ? " MULTI" : ""),
+ ((header->nlmsg_flags & NLM_F_ACK) ? " ACK" : ""),
+ ((header->nlmsg_flags & NLM_F_ECHO) ? " ECHO" : ""),
+ ((header->nlmsg_flags & NLM_F_DUMP_INTR) ? " BAD-SEQ" : ""));
+
+ SLOG(WiFi, log_level) << StringPrintf(
+ "sequence: %02x %02x %02x %02x = %u",
+ buf[8], buf[9], buf[10], buf[11], header->nlmsg_seq);
+ SLOG(WiFi, log_level) << StringPrintf(
+ "pid: %02x %02x %02x %02x = %u",
+ buf[12], buf[13], buf[14], buf[15], header->nlmsg_pid);
+ buf += sizeof(nlmsghdr);
+ num_bytes -= sizeof(nlmsghdr);
+ } else {
+ SLOG(WiFi, log_level) << "Not enough bytes (" << num_bytes
+ << ") for a complete nlmsghdr (requires "
+ << sizeof(nlmsghdr) << ").";
+ }
+
+ while (num_bytes) {
+ string output;
+ size_t bytes_this_row = min(num_bytes, static_cast<size_t>(32));
+ for (size_t i = 0; i < bytes_this_row; ++i) {
+ StringAppendF(&output, " %02x", *buf++);
+ }
+ SLOG(WiFi, log_level) << output;
+ num_bytes -= bytes_this_row;
+ }
+}
+
+// GenericNetlinkMessage
+
+ByteString GenericNetlinkMessage::EncodeHeader(uint32_t sequence_number,
+ uint16_t nlmsg_type) {
+ // Build nlmsghdr.
+ ByteString result(NetlinkMessage::EncodeHeader(sequence_number, nlmsg_type));
+ if (result.GetLength() == 0) {
+ LOG(ERROR) << "Couldn't encode message header.";
+ return result;
+ }
+
+ // Build and append the genl message header.
+ genlmsghdr genl_header;
+ genl_header.cmd = command();
+ genl_header.version = 1;
+ genl_header.reserved = 0;
+
+ ByteString genl_header_string(
+ reinterpret_cast<unsigned char *>(&genl_header), sizeof(genl_header));
+ size_t genlmsghdr_with_pad = NLMSG_ALIGN(sizeof(genl_header));
+ genl_header_string.Resize(genlmsghdr_with_pad); // Zero-fill.
+
+ nlmsghdr *pheader = reinterpret_cast<nlmsghdr *>(result.GetData());
+ pheader->nlmsg_len += genlmsghdr_with_pad;
+ result.Append(genl_header_string);
+ return result;
+}
+
+ByteString GenericNetlinkMessage::Encode(uint32_t sequence_number,
+ uint16_t nlmsg_type) {
+ ByteString result(EncodeHeader(sequence_number, nlmsg_type));
+ if (result.GetLength() == 0) {
+ LOG(ERROR) << "Couldn't encode message header.";
+ return result;
+ }
+
+ // Build and append attributes (padding is included by
+ // AttributeList::Encode).
+ ByteString attribute_string = attributes_->Encode();
+
+ // Need to re-calculate |header| since |Append|, above, moves the data.
+ nlmsghdr *pheader = reinterpret_cast<nlmsghdr *>(result.GetData());
+ pheader->nlmsg_len += attribute_string.GetLength();
+ result.Append(attribute_string);
+
+ return result;
+}
+
+bool GenericNetlinkMessage::InitAndStripHeader(ByteString *input) {
+ if (!input) {
+ LOG(ERROR) << "NULL input";
+ return false;
+ }
+ if (!NetlinkMessage::InitAndStripHeader(input)) {
+ return false;
+ }
// Read the genlmsghdr.
genlmsghdr *gnlh = reinterpret_cast<genlmsghdr *>(input->GetData());
@@ -138,6 +261,15 @@
return true;
}
+void GenericNetlinkMessage::Print(int log_level) const {
+ SLOG(WiFi, log_level) << StringPrintf("Message %s (%d)",
+ command_string(),
+ command());
+ attributes_->Print(log_level, 1);
+}
+
+// Nl80211Message
+
bool Nl80211Message::InitFromNlmsg(const nlmsghdr *const_msg) {
if (!const_msg) {
LOG(ERROR) << "Null |msg| parameter";
@@ -364,61 +496,6 @@
return true;
}
-void Nl80211Message::Print(int log_level) const {
- SLOG(WiFi, log_level) << StringPrintf("Message %s (%d)",
- command_string(),
- command());
- attributes_->Print(log_level, 1);
-}
-
-// static
-void Nl80211Message::PrintBytes(int log_level, const unsigned char *buf,
- size_t num_bytes) {
- SLOG(WiFi, log_level) << "Netlink Message -- Examining Bytes";
- if (!buf) {
- SLOG(WiFi, log_level) << "<NULL Buffer>";
- return;
- }
-
- if (num_bytes >= sizeof(nlmsghdr)) {
- const nlmsghdr *header = reinterpret_cast<const nlmsghdr *>(buf);
- SLOG(WiFi, log_level) << StringPrintf(
- "len: %02x %02x %02x %02x = %u bytes",
- buf[0], buf[1], buf[2], buf[3], header->nlmsg_len);
-
- SLOG(WiFi, log_level) << StringPrintf(
- "type | flags: %02x %02x %02x %02x - type:%u flags:%s%s%s%s%s",
- buf[4], buf[5], buf[6], buf[7], header->nlmsg_type,
- ((header->nlmsg_flags & NLM_F_REQUEST) ? " REQUEST" : ""),
- ((header->nlmsg_flags & NLM_F_MULTI) ? " MULTI" : ""),
- ((header->nlmsg_flags & NLM_F_ACK) ? " ACK" : ""),
- ((header->nlmsg_flags & NLM_F_ECHO) ? " ECHO" : ""),
- ((header->nlmsg_flags & NLM_F_DUMP_INTR) ? " BAD-SEQ" : ""));
-
- SLOG(WiFi, log_level) << StringPrintf(
- "sequence: %02x %02x %02x %02x = %u",
- buf[8], buf[9], buf[10], buf[11], header->nlmsg_seq);
- SLOG(WiFi, log_level) << StringPrintf(
- "pid: %02x %02x %02x %02x = %u",
- buf[12], buf[13], buf[14], buf[15], header->nlmsg_pid);
- buf += sizeof(nlmsghdr);
- num_bytes -= sizeof(nlmsghdr);
- } else {
- SLOG(WiFi, log_level) << "Not enough bytes (" << num_bytes
- << ") for a complete nlmsghdr (requires "
- << sizeof(nlmsghdr) << ").";
- }
-
- while (num_bytes) {
- string output;
- size_t bytes_this_row = min(num_bytes, static_cast<size_t>(32));
- for (size_t i = 0; i < bytes_this_row; ++i) {
- StringAppendF(&output, " %02x", *buf++);
- }
- SLOG(WiFi, log_level) << output;
- num_bytes -= bytes_this_row;
- }
-}
// Helper function to provide a string for a MAC address.
bool Nl80211Message::GetMacAttributeString(int id, string *value) const {
@@ -491,61 +568,6 @@
return true;
}
-// Protected members.
-
-string Nl80211Message::GetHeaderString() const {
- char ifname[IF_NAMESIZE] = "";
- uint32_t ifindex = UINT32_MAX;
- bool ifindex_exists = const_attributes()->GetU32AttributeValue(
- NL80211_ATTR_IFINDEX, &ifindex);
-
- uint32_t wifi = UINT32_MAX;
- bool wifi_exists = const_attributes()->GetU32AttributeValue(
- NL80211_ATTR_WIPHY, &wifi);
-
- string output;
- if (ifindex_exists && wifi_exists) {
- StringAppendF(&output, "%s (phy #%" PRIu32 "): ",
- (if_indextoname(ifindex, ifname) ? ifname : "<unknown>"),
- wifi);
- } else if (ifindex_exists) {
- StringAppendF(&output, "%s: ",
- (if_indextoname(ifindex, ifname) ? ifname : "<unknown>"));
- } else if (wifi_exists) {
- StringAppendF(&output, "phy #%" PRIu32 "u: ", wifi);
- }
-
- return output;
-}
-
-string Nl80211Message::StringFromFrame(int attr_name) const {
- string output;
- ByteString frame_data;
- if (const_attributes()->GetRawAttributeValue(attr_name, &frame_data) &&
- !frame_data.IsEmpty()) {
- Nl80211Frame frame(frame_data);
- frame.ToString(&output);
- } else {
- output.append(" [no frame]");
- }
-
- return output;
-}
-
-// static
-string Nl80211Message::StringFromKeyType(nl80211_key_type key_type) {
- switch (key_type) {
- case NL80211_KEYTYPE_GROUP:
- return "Group";
- case NL80211_KEYTYPE_PAIRWISE:
- return "Pairwise";
- case NL80211_KEYTYPE_PEERKEY:
- return "PeerKey";
- default:
- return "<Unknown Key Type>";
- }
-}
-
// static
string Nl80211Message::StringFromMacAddress(const uint8_t *arg) {
string output;
@@ -564,44 +586,6 @@
}
// static
-string Nl80211Message::StringFromRegInitiator(__u8 initiator) {
- switch (initiator) {
- case NL80211_REGDOM_SET_BY_CORE:
- return "the wireless core upon initialization";
- case NL80211_REGDOM_SET_BY_USER:
- return "a user";
- case NL80211_REGDOM_SET_BY_DRIVER:
- return "a driver";
- case NL80211_REGDOM_SET_BY_COUNTRY_IE:
- return "a country IE";
- default:
- return "<Unknown Reg Initiator>";
- }
-}
-
-// static
-string Nl80211Message::StringFromSsid(const uint8_t len,
- const uint8_t *data) {
- string output;
- if (!data) {
- StringAppendF(&output, "<Error from %s, NULL parameter>", __func__);
- LOG(ERROR) << "|data| parameter is NULL.";
- return output;
- }
-
- for (int i = 0; i < len; ++i) {
- if (data[i] == ' ')
- output.append(" ");
- else if (isprint(data[i]))
- StringAppendF(&output, "%c", static_cast<char>(data[i]));
- else
- StringAppendF(&output, "\\x%2x", data[i]);
- }
-
- return output;
-}
-
-// static
string Nl80211Message::StringFromReason(uint16_t status) {
map<uint16_t, string>::const_iterator match;
match = reason_code_string_->find(status);
@@ -633,65 +617,6 @@
return match->second;
}
-ByteString Nl80211Message::EncodeHeader(uint32_t sequence_number,
- uint16_t nlmsg_type) {
- ByteString result;
- sequence_number_ = sequence_number;
- if (sequence_number_ == kBroadcastSequenceNumber) {
- LOG(ERROR) << "Couldn't get a legal sequence number";
- return result;
- }
-
- // Build netlink header.
- nlmsghdr header;
- size_t nlmsghdr_with_pad = NLMSG_ALIGN(sizeof(header));
- header.nlmsg_len = nlmsghdr_with_pad;
- header.nlmsg_type = nlmsg_type;
- header.nlmsg_flags = NLM_F_REQUEST;
- header.nlmsg_seq = sequence_number_;
- header.nlmsg_pid = getpid();
-
- // Netlink header + pad.
- result.Append(ByteString(reinterpret_cast<unsigned char *>(&header),
- sizeof(header)));
- result.Resize(nlmsghdr_with_pad); // Zero-fill pad space (if any).
-
- // Build and append the genl message header.
- genlmsghdr genl_header;
- genl_header.cmd = command();
- genl_header.version = 1;
- genl_header.reserved = 0;
-
- ByteString genl_header_string(
- reinterpret_cast<unsigned char *>(&genl_header), sizeof(genl_header));
- size_t genlmsghdr_with_pad = NLMSG_ALIGN(sizeof(genl_header));
- genl_header_string.Resize(genlmsghdr_with_pad); // Zero-fill.
-
- nlmsghdr *pheader = reinterpret_cast<nlmsghdr *>(result.GetData());
- pheader->nlmsg_len += genlmsghdr_with_pad;
- result.Append(genl_header_string);
- return result;
-}
-
-ByteString Nl80211Message::Encode(uint32_t sequence_number,
- uint16_t nlmsg_type) {
- ByteString result(EncodeHeader(sequence_number, nlmsg_type));
- if (result.GetLength() == 0) {
- LOG(ERROR) << "Couldn't encode message header.";
- return result;
- }
-
- // Build and append attributes (padding is included by
- // AttributeList::Encode).
- ByteString attribute_bytes = attributes_->Encode();
-
- // Need to re-calculate |header| since |Append|, above, moves the data.
- nlmsghdr *pheader = reinterpret_cast<nlmsghdr *>(result.GetData());
- pheader->nlmsg_len += attribute_bytes.GetLength();
- result.Append(attribute_bytes);
-
- return result;
-}
Nl80211Frame::Nl80211Frame(const ByteString &raw_frame)
: frame_type_(kIllegalFrameType), reason_(UINT16_MAX), status_(UINT16_MAX),
@@ -914,13 +839,13 @@
// Factory class.
//
-Nl80211Message *Nl80211MessageFactory::CreateMessage(nlmsghdr *msg) {
+NetlinkMessage *NetlinkMessageFactory::CreateMessage(nlmsghdr *msg) {
if (!msg) {
LOG(ERROR) << "NULL |msg| parameter";
return NULL;
}
- scoped_ptr<Nl80211Message> message;
+ scoped_ptr<NetlinkMessage> message;
void *payload = nlmsg_data(msg);
if (msg->nlmsg_type == NLMSG_NOOP) {