shill: Makes unknown nl80211 messages look like Nl80211Messages.
Before, when NetlinkMessage::CreateMessage was given an nl80211 message
that it didn't recognize, the code generated something that was a
sort-of hybrid between a vanilla NetlinkMessage and an Nl80211Message
(with disasterous results). This makes the unknown message look just
like an Nl80211Message.
The specific problem this addresses happened because a developer added a
new message type but hadn't, yet, added it to the factory. This generated
an UnknownMessage and passed it to the message handler.
BUG=None
TEST=unitest
Change-Id: I78bc0861725c660f794c9eec2b99d23dded7d7a2
Reviewed-on: https://gerrit.chromium.org/gerrit/50525
Commit-Queue: Wade Guthrie <wdg@chromium.org>
Reviewed-by: Wade Guthrie <wdg@chromium.org>
Tested-by: Wade Guthrie <wdg@chromium.org>
diff --git a/generic_netlink_message.cc b/generic_netlink_message.cc
index 79526e7..3e0d04d 100644
--- a/generic_netlink_message.cc
+++ b/generic_netlink_message.cc
@@ -153,6 +153,7 @@
return new GetFamilyMessage();
default:
LOG(WARNING) << "Unknown/unhandled netlink control message " << gnlh->cmd;
+ return new UnknownControlMessage(gnlh->cmd);
break;
}
return NULL;
diff --git a/generic_netlink_message.h b/generic_netlink_message.h
index 3393bba..b6f9438 100644
--- a/generic_netlink_message.h
+++ b/generic_netlink_message.h
@@ -101,6 +101,9 @@
// Message factory for all types of Control netlink message.
static NetlinkMessage *CreateMessage(const nlmsghdr *const_msg);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ControlNetlinkMessage);
};
class NewFamilyMessage : public ControlNetlinkMessage {
@@ -125,6 +128,17 @@
DISALLOW_COPY_AND_ASSIGN(GetFamilyMessage);
};
+class UnknownControlMessage : public ControlNetlinkMessage {
+ public:
+ explicit UnknownControlMessage(uint8_t command)
+ : ControlNetlinkMessage(command, "<UNKNOWN CONTROL MESSAGE>"),
+ command_(command) {}
+
+ private:
+ uint8_t command_;
+ DISALLOW_COPY_AND_ASSIGN(UnknownControlMessage);
+};
+
} // namespace shill
#endif // SHILL_GENERIC_NETLINK_MESSAGE_H_
diff --git a/netlink_message_unittest.cc b/netlink_message_unittest.cc
index 8791220..93b9a04 100644
--- a/netlink_message_unittest.cc
+++ b/netlink_message_unittest.cc
@@ -14,18 +14,22 @@
#include <string>
#include <vector>
+#include <base/stringprintf.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include "shill/mock_log.h"
#include "shill/mock_netlink_socket.h"
#include "shill/netlink_attribute.h"
#include "shill/refptr_types.h"
using base::Bind;
+using base::StringPrintf;
using base::Unretained;
using std::string;
using std::vector;
using testing::_;
+using testing::EndsWith;
using testing::Invoke;
using testing::Return;
using testing::Test;
@@ -344,6 +348,20 @@
0x03, 0x00, 0x00, 0x00,
};
+// This is just a NL80211_CMD_NEW_STATION message with the command changed to
+// 0xfe (which is, intentionally, not a supported command).
+
+const unsigned char kCmdNL80211_CMD_UNKNOWN = 0xfe;
+const unsigned char kNL80211_CMD_UNKNOWN[] = {
+ 0x34, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xfe, 0x01, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x06, 0x00,
+ 0xc0, 0x3f, 0x0e, 0x77, 0xe8, 0x7f, 0x00, 0x00,
+ 0x08, 0x00, 0x2e, 0x00, 0x13, 0x01, 0x00, 0x00,
+ 0x04, 0x00, 0x15, 0x00,
+};
+
const char kGetFamilyCommandString[] = "CTRL_CMD_GETFAMILY";
} // namespace
@@ -827,4 +845,22 @@
}
}
+// This test is to ensure that an unknown nl80211 message generates an
+// Nl80211UnknownMessage with all Nl80211 parts.
+TEST_F(NetlinkMessageTest, Parse_NL80211_CMD_UNKNOWN) {
+ ScopedMockLog log;
+ string logmessage = StringPrintf(
+ "Unknown/unhandled netlink nl80211 message 0x%02x",
+ kCmdNL80211_CMD_UNKNOWN);
+ EXPECT_CALL(log, Log(logging::LOG_WARNING, _, EndsWith(logmessage.c_str())));
+ NetlinkMessage *netlink_message =
+ message_factory_.CreateMessage(
+ reinterpret_cast<const nlmsghdr *>(kNL80211_CMD_UNKNOWN));
+ ASSERT_NE(reinterpret_cast<NetlinkMessage *>(NULL), netlink_message);
+ EXPECT_EQ(kNl80211FamilyId, netlink_message->message_type());
+ // The follwing is legal if the message_type is kNl80211FamilyId.
+ Nl80211Message *message = dynamic_cast<Nl80211Message *>(netlink_message);
+ EXPECT_EQ(kCmdNL80211_CMD_UNKNOWN, message->command());
+}
+
} // namespace shill
diff --git a/nl80211_message.cc b/nl80211_message.cc
index 738e0e4..5b142c3 100644
--- a/nl80211_message.cc
+++ b/nl80211_message.cc
@@ -723,7 +723,9 @@
case UnprotDisassociateMessage::kCommand:
return new UnprotDisassociateMessage();
default:
- LOG(WARNING) << "Unknown/unhandled netlink nl80211 message " << gnlh->cmd;
+ LOG(WARNING) << StringPrintf(
+ "Unknown/unhandled netlink nl80211 message 0x%02x", gnlh->cmd);
+ return new UnknownNl80211Message(gnlh->cmd);
break;
}
return NULL;
diff --git a/nl80211_message.h b/nl80211_message.h
index d6ed7af..1eb080f 100644
--- a/nl80211_message.h
+++ b/nl80211_message.h
@@ -418,6 +418,18 @@
};
+class UnknownNl80211Message : public Nl80211Message {
+ public:
+ explicit UnknownNl80211Message(uint8_t command)
+ : Nl80211Message(command, "<UNKNOWN NL80211 MESSAGE>"),
+ command_(command) {}
+
+ private:
+ uint8_t command_;
+ DISALLOW_COPY_AND_ASSIGN(UnknownNl80211Message);
+};
+
+
class UnprotDeauthenticateMessage : public Nl80211Message {
public:
static const uint8_t kCommand;