shill: Combines user- and kernel-bound nl80211 messages.

The UserBoundNlMessage and KernelBoundNlMessage classes are merged
into Nl80211Message.

As part of combining the two messages, the code was modified to use raw
socket writes instead of using libnl (in order to test kernel-bound
Nl80211Message writing) for sending a message.  Note, however, that
libnl code is still liberally used; there's just less use of it than
before.  Some (a little) effort was made to be consistent with the
RTNLHandler code toward combining the codebases, eventually.

BUG=chromium-os:36099, chromium-os:36638
TEST=unittests and manual tests (I added code to create an
Nl80211Message, send that message to the kernel, and display the output;
I hand inspected the output).

Change-Id: I7b04e49cee84745d1b02f1dd2b064f9e9a0aada2
Reviewed-on: https://gerrit.chromium.org/gerrit/40266
Commit-Queue: Wade Guthrie <wdg@chromium.org>
Reviewed-by: Wade Guthrie <wdg@chromium.org>
Tested-by: Wade Guthrie <wdg@chromium.org>
diff --git a/Makefile b/Makefile
index ae41748..75a2d94 100644
--- a/Makefile
+++ b/Makefile
@@ -219,7 +219,6 @@
 	ip_address.o \
 	ipconfig.o \
 	ipconfig_dbus_adaptor.o \
-	kernel_bound_nlmessage.o \
 	key_file_store.o \
 	key_value_store.o \
 	link_monitor.o \
@@ -252,6 +251,7 @@
 	modem_simple_proxy.o \
 	netlink_socket.o \
 	nl80211_attribute.o \
+	nl80211_message.o \
 	nl80211_socket.o \
 	nss.o \
 	openvpn_driver.o \
@@ -287,7 +287,6 @@
 	supplicant_network_proxy.o \
 	supplicant_process_proxy.o \
 	technology.o \
-	user_bound_nlmessage.o \
 	virtio_ethernet.o \
 	vpn.o \
 	vpn_driver.o \
diff --git a/attribute_list.cc b/attribute_list.cc
index ea797a0..e57f734 100644
--- a/attribute_list.cc
+++ b/attribute_list.cc
@@ -60,6 +60,16 @@
   return output;
 }
 
+ByteString AttributeList::Encode() const {
+  ByteString result;
+  map<int, AttributePointer>::const_iterator i;
+
+  for (i = attributes_.begin(); i != attributes_.end(); ++i) {
+    result.Append(i->second->Encode());
+  }
+  return result;
+}
+
 // U8 Attribute.
 
 bool AttributeList::GetU8AttributeValue(int id, uint8_t *value) const {
diff --git a/attribute_list.h b/attribute_list.h
index e733d01..274a0cd 100644
--- a/attribute_list.h
+++ b/attribute_list.h
@@ -37,6 +37,11 @@
 
   std::string ToString() const;
 
+  // Returns the attributes as the payload portion of a netlink message
+  // suitable for Sockets::Send.  Return value is empty on failure (or if no
+  // attributes exist).
+  ByteString Encode() const;
+
   bool GetU8AttributeValue(int id, uint8_t *value) const;
   bool GetU16AttributeValue(int id, uint16_t *value) const;
   bool GetU32AttributeValue(int id, uint32_t *value) const;
@@ -55,7 +60,7 @@
   // them.
   bool GetRawAttributeValue(int id, ByteString *output) const;
   // TODO(wdg): |GetRawAttribute| is a stopgap to support various
-  // UserBoundNlMessage::ToString methods and must, once those are re-written,
+  // Nl80211Message::ToString methods and must, once those are re-written,
   // be destroyed.
   const Nl80211RawAttribute *GetRawAttribute(int id) const;
 
diff --git a/callback80211_metrics.cc b/callback80211_metrics.cc
index 41cf24d..a309aa8 100644
--- a/callback80211_metrics.cc
+++ b/callback80211_metrics.cc
@@ -9,7 +9,7 @@
 #include "shill/link_monitor.h"
 #include "shill/logging.h"
 #include "shill/metrics.h"
-#include "shill/user_bound_nlmessage.h"
+#include "shill/nl80211_message.h"
 
 namespace shill {
 
@@ -19,7 +19,7 @@
 }
 
 void Callback80211Metrics::Config80211MessageCallback(
-    const UserBoundNlMessage &message) {
+    const Nl80211Message &message) {
   SLOG(WiFi, 3) << "Received " << message.message_type_string()
                 << " (" << + message.message_type() << ")";
   if (metrics_ &&
diff --git a/callback80211_metrics.h b/callback80211_metrics.h
index 7bdd4ea..bdd2f6c 100644
--- a/callback80211_metrics.h
+++ b/callback80211_metrics.h
@@ -15,7 +15,7 @@
 namespace shill {
 
 class Metrics;
-class UserBoundNlMessage;
+class Nl80211Message;
 
 // Config80211 callback object that sends stuff to UMA metrics.
 class Callback80211Metrics : public Callback80211Object {
@@ -23,7 +23,7 @@
   explicit Callback80211Metrics(Metrics *metrics);
 
  protected:
-  virtual void Config80211MessageCallback(const UserBoundNlMessage &msg);
+  virtual void Config80211MessageCallback(const Nl80211Message &msg);
 
  private:
   static const char kMetricLinkDisconnectCount[];
diff --git a/callback80211_object.cc b/callback80211_object.cc
index 5268ac6..d10bfe4 100644
--- a/callback80211_object.cc
+++ b/callback80211_object.cc
@@ -14,8 +14,8 @@
 #include "shill/link_monitor.h"
 #include "shill/logging.h"
 #include "shill/nl80211_attribute.h"
+#include "shill/nl80211_message.h"
 #include "shill/scope_logger.h"
-#include "shill/user_bound_nlmessage.h"
 
 using base::Bind;
 using base::StringAppendF;
@@ -34,7 +34,7 @@
 }
 
 void Callback80211Object::Config80211MessageCallback(
-    const UserBoundNlMessage &message) {
+    const Nl80211Message &message) {
   // Show the message-type-specific version of the message.
   string output("@");
   StringAppendF(&output, "%s", message.ToString().c_str());
@@ -52,8 +52,7 @@
   return Config80211::GetInstance()->RemoveBroadcastCallback(callback_);
 }
 
-void Callback80211Object::ReceiveConfig80211Message(
-    const UserBoundNlMessage &msg) {
+void Callback80211Object::ReceiveConfig80211Message(const Nl80211Message &msg) {
   Config80211MessageCallback(msg);
 }
 
diff --git a/callback80211_object.h b/callback80211_object.h
index 120cb1c..02293ae 100644
--- a/callback80211_object.h
+++ b/callback80211_object.h
@@ -15,7 +15,7 @@
 
 namespace shill {
 
-class UserBoundNlMessage;
+class Nl80211Message;
 
 // Example Config80211 callback object; the callback prints a description of
 // each message with its attributes.
@@ -31,10 +31,10 @@
  protected:
   // When installed, this is the method Config80211 will call when it gets a
   // message from the mac80211 drivers.
-  virtual void Config80211MessageCallback(const UserBoundNlMessage &msg);
+  virtual void Config80211MessageCallback(const Nl80211Message &msg);
 
  private:
-  void ReceiveConfig80211Message(const UserBoundNlMessage &msg);
+  void ReceiveConfig80211Message(const Nl80211Message &msg);
 
   base::WeakPtrFactory<Callback80211Object> weak_ptr_factory_;
   Config80211::Callback callback_;
diff --git a/config80211.cc b/config80211.cc
index 320e9cc..21d794a 100644
--- a/config80211.cc
+++ b/config80211.cc
@@ -15,11 +15,10 @@
 #include <base/stl_util.h>
 
 #include "shill/io_handler.h"
-#include "shill/kernel_bound_nlmessage.h"
 #include "shill/logging.h"
+#include "shill/nl80211_message.h"
 #include "shill/nl80211_socket.h"
 #include "shill/scope_logger.h"
-#include "shill/user_bound_nlmessage.h"
 
 using base::Bind;
 using base::LazyInstance;
@@ -146,14 +145,18 @@
   broadcast_callbacks_.clear();
 }
 
-bool Config80211::SendMessage(KernelBoundNlMessage *message,
+bool Config80211::SendMessage(Nl80211Message *message,
                               const Callback &callback) {
   if (!message) {
     LOG(ERROR) << "Message is NULL.";
     return false;
   }
-  uint32 sequence_number = sock_->Send(message);
+  uint32 sequence_number = message->sequence_number();
   if (!sequence_number) {
+    sequence_number = sock_->GetSequenceNumber();
+    message->set_sequence_number(sequence_number);
+  }
+  if (!sock_->SendMessage(message)) {
     LOG(ERROR) << "Failed to send nl80211 message.";
     return false;
   }
@@ -170,7 +173,7 @@
   return true;
 }
 
-bool Config80211::RemoveMessageCallback(const KernelBoundNlMessage &message) {
+bool Config80211::RemoveMessageCallback(const Nl80211Message &message) {
   if (!ContainsKey(message_callbacks_, message.sequence_number())) {
     return false;
   }
@@ -281,8 +284,7 @@
   const uint32 sequence_number = msg->nlmsg_seq;
   SLOG(WiFi, 3) << "\t  Entering " << __func__
                 << "( msg:" << sequence_number << ")";
-  scoped_ptr<UserBoundNlMessage> message(
-      UserBoundNlMessageFactory::CreateMessage(msg));
+  scoped_ptr<Nl80211Message> message(Nl80211MessageFactory::CreateMessage(msg));
   if (message == NULL) {
     SLOG(WiFi, 3) << __func__ << "(msg:NULL)";
     return NL_SKIP;  // Skip current message, continue parsing buffer.
diff --git a/config80211.h b/config80211.h
index 300230a..d06af48 100644
--- a/config80211.h
+++ b/config80211.h
@@ -30,7 +30,7 @@
 //    user calls Config80211::SubscribeToEvents, Config80211 installs
 //    OnRawNlMessageReceived as a netlink callback function (described below).
 //    OnRawNlMessageReceived, in turn, parses the message from cfg80211 and
-//    calls Config80211::Callback with the resultant UserBoundNlMessage.
+//    calls Config80211::Callback with the resultant Nl80211Message.
 //
 // Netlink Callback -
 //    Netlink callbacks are mechanisms installed by the user (well, by
@@ -79,8 +79,7 @@
 
 namespace shill {
 
-class KernelBoundNlMessage;
-class UserBoundNlMessage;
+class Nl80211Message;
 
 // Provides a transport-independent ability to receive status from the wifi
 // configuration.  In its current implementation, it uses the netlink socket
@@ -89,7 +88,7 @@
 // Config80211 is a singleton and, as such, coordinates access to libnl.
 class Config80211 {
  public:
-  typedef base::Callback<void(const UserBoundNlMessage &)> Callback;
+  typedef base::Callback<void(const Nl80211Message &)> Callback;
 
   // The different kinds of events to which we can subscribe (and receive)
   // from cfg80211.
@@ -138,10 +137,10 @@
   // installing a callback to handle it.
   // TODO(wdg): Eventually, this should also include a timeout and a callback
   // to call in case of timeout.
-  bool SendMessage(KernelBoundNlMessage *message, const Callback &callback);
+  bool SendMessage(Nl80211Message *message, const Callback &callback);
 
   // Uninstall a Config80211 Callback for a specific message.
-  bool RemoveMessageCallback(const KernelBoundNlMessage &message);
+  bool RemoveMessageCallback(const Nl80211Message &message);
 
   // Return a string corresponding to the passed-in EventType.
   static bool GetEventTypeString(EventType type, std::string *value);
diff --git a/config80211_unittest.cc b/config80211_unittest.cc
index 4d00231..c6d16f2 100644
--- a/config80211_unittest.cc
+++ b/config80211_unittest.cc
@@ -3,8 +3,8 @@
 // found in the LICENSE file.
 
 // This file provides tests for individual messages.  It tests
-// UserBoundNlMessageFactory's ability to create specific message types and it
-// tests the various UserBoundNlMessage types' ability to parse those
+// Nl80211MessageFactory's ability to create specific message types and it
+// tests the various Nl80211Message types' ability to parse those
 // messages.
 
 // This file tests the public interface to Config80211.
@@ -25,12 +25,11 @@
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
-#include "shill/kernel_bound_nlmessage.h"
 #include "shill/mock_callback80211_object.h"
 #include "shill/mock_nl80211_socket.h"
 #include "shill/nl80211_attribute.h"
+#include "shill/nl80211_message.h"
 #include "shill/nl80211_socket.h"
-#include "shill/user_bound_nlmessage.h"
 
 using base::Bind;
 using base::Unretained;
@@ -345,17 +344,23 @@
   0x03, 0x00, 0x00, 0x00,
 };
 
+const char kGetFamilyCommandString[] = "CTRL_CMD_GETFAMILY";
+
 }  // namespace
-uint32 MockNl80211Socket::Send(KernelBoundNlMessage *message) {
-  // Don't need a real family id; this is never sent.
-  const uint32 family_id = 0;
-  uint32 sequence_number = ++sequence_number_;
-  if (genlmsg_put(message->message(), NL_AUTO_PID, sequence_number, family_id,
-                  0, 0, message->command(), 0) == NULL) {
-    LOG(ERROR) << "genlmsg_put returned a NULL pointer.";
-    return 0;
+
+bool MockNl80211Socket::SendMessage(Nl80211Message *message) {
+  if (!message) {
+    LOG(ERROR) << "Null |message|";
+    return false;
   }
-  return sequence_number;
+  return true;
+}
+
+uint32_t MockNl80211Socket::GetSequenceNumber() {
+  // Sequence number 0 is reserved for broadcast messages from the kernel.
+  if (++sequence_number_ == 0)
+    ++sequence_number_;
+  return sequence_number_;
 }
 
 class Config80211Test : public Test {
@@ -382,7 +387,7 @@
  public:
   TestCallbackObject() : callback_(Bind(&TestCallbackObject::MessageHandler,
                                         Unretained(this))) { }
-  void MessageHandler(const UserBoundNlMessage &msg) {
+  void MessageHandler(const Nl80211Message &msg) {
   }
   const Config80211::Callback &GetCallback() const { return callback_; }
 
@@ -509,13 +514,11 @@
   MockCallback80211 callback_broadcast;
   EXPECT_TRUE(callback_broadcast.InstallAsBroadcastCallback());
 
-  KernelBoundNlMessage sent_message_1(CTRL_CMD_GETFAMILY);
+  Nl80211Message sent_message_1(CTRL_CMD_GETFAMILY, kGetFamilyCommandString);
   MockCallback80211 callback_sent_1;
-  EXPECT_TRUE(sent_message_1.Init());
 
-  KernelBoundNlMessage sent_message_2(CTRL_CMD_GETFAMILY);
+  Nl80211Message sent_message_2(CTRL_CMD_GETFAMILY, kGetFamilyCommandString);
   MockCallback80211 callback_sent_2;
-  EXPECT_TRUE(sent_message_2.Init());
 
   // Set up the received message as a response to sent_message_1.
   scoped_array<unsigned char> message_memory(
@@ -569,11 +572,11 @@
 }
 
 TEST_F(Config80211Test, NL80211_CMD_TRIGGER_SCAN) {
-  UserBoundNlMessage *message = UserBoundNlMessageFactory::CreateMessage(
+  Nl80211Message *message = Nl80211MessageFactory::CreateMessage(
       const_cast<nlmsghdr *>(
         reinterpret_cast<const nlmsghdr *>(kNL80211_CMD_TRIGGER_SCAN)));
 
-  EXPECT_NE(message, reinterpret_cast<UserBoundNlMessage *>(NULL));
+  EXPECT_NE(message, reinterpret_cast<Nl80211Message *>(NULL));
   EXPECT_EQ(message->message_type(), NL80211_CMD_TRIGGER_SCAN);
 
   {
@@ -618,11 +621,11 @@
 }
 
 TEST_F(Config80211Test, NL80211_CMD_NEW_SCAN_RESULTS) {
-  UserBoundNlMessage *message = UserBoundNlMessageFactory::CreateMessage(
+  Nl80211Message *message = Nl80211MessageFactory::CreateMessage(
       const_cast<nlmsghdr *>(
         reinterpret_cast<const nlmsghdr *>(kNL80211_CMD_NEW_SCAN_RESULTS)));
 
-  EXPECT_NE(message, reinterpret_cast<UserBoundNlMessage *>(NULL));
+  EXPECT_NE(message, reinterpret_cast<Nl80211Message *>(NULL));
   EXPECT_EQ(message->message_type(), NL80211_CMD_NEW_SCAN_RESULTS);
 
   {
@@ -667,11 +670,11 @@
 }
 
 TEST_F(Config80211Test, NL80211_CMD_NEW_STATION) {
-  UserBoundNlMessage *message = UserBoundNlMessageFactory::CreateMessage(
+  Nl80211Message *message = Nl80211MessageFactory::CreateMessage(
       const_cast<nlmsghdr *>(
         reinterpret_cast<const nlmsghdr *>(kNL80211_CMD_NEW_STATION)));
 
-  EXPECT_NE(message, reinterpret_cast<UserBoundNlMessage *>(NULL));
+  EXPECT_NE(message, reinterpret_cast<Nl80211Message *>(NULL));
   EXPECT_EQ(message->message_type(), NL80211_CMD_NEW_STATION);
 
   {
@@ -703,11 +706,11 @@
 }
 
 TEST_F(Config80211Test, NL80211_CMD_AUTHENTICATE) {
-  UserBoundNlMessage *message = UserBoundNlMessageFactory::CreateMessage(
+  Nl80211Message *message = Nl80211MessageFactory::CreateMessage(
       const_cast<nlmsghdr *>(
         reinterpret_cast<const nlmsghdr *>(kNL80211_CMD_AUTHENTICATE)));
 
-  EXPECT_NE(message, reinterpret_cast<UserBoundNlMessage *>(NULL));
+  EXPECT_NE(message, reinterpret_cast<Nl80211Message *>(NULL));
   EXPECT_EQ(message->message_type(), NL80211_CMD_AUTHENTICATE);
 
   {
@@ -737,11 +740,11 @@
 }
 
 TEST_F(Config80211Test, NL80211_CMD_ASSOCIATE) {
-  UserBoundNlMessage *message = UserBoundNlMessageFactory::CreateMessage(
+  Nl80211Message *message = Nl80211MessageFactory::CreateMessage(
       const_cast<nlmsghdr *>(
         reinterpret_cast<const nlmsghdr *>(kNL80211_CMD_ASSOCIATE)));
 
-  EXPECT_NE(message, reinterpret_cast<UserBoundNlMessage *>(NULL));
+  EXPECT_NE(message, reinterpret_cast<Nl80211Message *>(NULL));
   EXPECT_EQ(message->message_type(), NL80211_CMD_ASSOCIATE);
 
   {
@@ -771,11 +774,11 @@
 }
 
 TEST_F(Config80211Test, NL80211_CMD_CONNECT) {
-  UserBoundNlMessage *message = UserBoundNlMessageFactory::CreateMessage(
+  Nl80211Message *message = Nl80211MessageFactory::CreateMessage(
       const_cast<nlmsghdr *>(
         reinterpret_cast<const nlmsghdr *>(kNL80211_CMD_CONNECT)));
 
-  EXPECT_NE(message, reinterpret_cast<UserBoundNlMessage *>(NULL));
+  EXPECT_NE(message, reinterpret_cast<Nl80211Message *>(NULL));
   EXPECT_EQ(message->message_type(), NL80211_CMD_CONNECT);
 
   {
@@ -814,11 +817,11 @@
 }
 
 TEST_F(Config80211Test, NL80211_CMD_DEAUTHENTICATE) {
-  UserBoundNlMessage *message = UserBoundNlMessageFactory::CreateMessage(
+  Nl80211Message *message = Nl80211MessageFactory::CreateMessage(
       const_cast<nlmsghdr *>(
         reinterpret_cast<const nlmsghdr *>(kNL80211_CMD_DEAUTHENTICATE)));
 
-  EXPECT_NE(message, reinterpret_cast<UserBoundNlMessage *>(NULL));
+  EXPECT_NE(message, reinterpret_cast<Nl80211Message *>(NULL));
   EXPECT_EQ(message->message_type(), NL80211_CMD_DEAUTHENTICATE);
 
   {
@@ -848,11 +851,11 @@
 }
 
 TEST_F(Config80211Test, NL80211_CMD_DISCONNECT) {
-  UserBoundNlMessage *message = UserBoundNlMessageFactory::CreateMessage(
+  Nl80211Message *message = Nl80211MessageFactory::CreateMessage(
       const_cast<nlmsghdr *>(
         reinterpret_cast<const nlmsghdr *>(kNL80211_CMD_DISCONNECT)));
 
-  EXPECT_NE(message, reinterpret_cast<UserBoundNlMessage *>(NULL));
+  EXPECT_NE(message, reinterpret_cast<Nl80211Message *>(NULL));
   EXPECT_EQ(message->message_type(), NL80211_CMD_DISCONNECT);
 
   {
@@ -881,11 +884,11 @@
 }
 
 TEST_F(Config80211Test, NL80211_CMD_NOTIFY_CQM) {
-  UserBoundNlMessage *message = UserBoundNlMessageFactory::CreateMessage(
+  Nl80211Message *message = Nl80211MessageFactory::CreateMessage(
       const_cast<nlmsghdr *>(
         reinterpret_cast<const nlmsghdr *>(kNL80211_CMD_NOTIFY_CQM)));
 
-  EXPECT_NE(message, reinterpret_cast<UserBoundNlMessage *>(NULL));
+  EXPECT_NE(message, reinterpret_cast<Nl80211Message *>(NULL));
   EXPECT_EQ(message->message_type(), NL80211_CMD_NOTIFY_CQM);
 
 
@@ -926,11 +929,11 @@
 }
 
 TEST_F(Config80211Test, NL80211_CMD_DISASSOCIATE) {
-  UserBoundNlMessage *message = UserBoundNlMessageFactory::CreateMessage(
+  Nl80211Message *message = Nl80211MessageFactory::CreateMessage(
       const_cast<nlmsghdr *>(
         reinterpret_cast<const nlmsghdr *>(kNL80211_CMD_DISASSOCIATE)));
 
-  EXPECT_NE(message, reinterpret_cast<UserBoundNlMessage *>(NULL));
+  EXPECT_NE(message, reinterpret_cast<Nl80211Message *>(NULL));
   EXPECT_EQ(message->message_type(), NL80211_CMD_DISASSOCIATE);
 
 
diff --git a/kernel_bound_nlmessage.cc b/kernel_bound_nlmessage.cc
deleted file mode 100644
index e1b8e7c..0000000
--- a/kernel_bound_nlmessage.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "shill/kernel_bound_nlmessage.h"
-
-#include <netlink/msg.h>
-
-#include "shill/logging.h"
-
-namespace shill {
-
-KernelBoundNlMessage::~KernelBoundNlMessage() {
-  if (message_) {
-    nlmsg_free(message_);
-    message_ = NULL;
-  }
-}
-
-bool KernelBoundNlMessage::Init() {
-  message_ = nlmsg_alloc();
-
-  if (!message_) {
-    LOG(ERROR) << "Couldn't allocate |message_|";
-    return false;
-  }
-
-  return true;
-}
-
-int KernelBoundNlMessage::AddAttribute(int attrtype, int attrlen,
-                                       const void *data) {
-  if (!data) {
-    LOG(ERROR) << "NULL |data| parameter";
-    return -1;
-  }
-  if (!message_) {
-    LOG(ERROR) << "NULL |message_|.";
-    return -1;
-  }
-  return nla_put(message_, attrtype, attrlen, data);
-}
-
-uint32 KernelBoundNlMessage::sequence_number() const {
-  if (message_ && nlmsg_hdr(message_)) {
-    return nlmsg_hdr(message_)->nlmsg_seq;
-  }
-  return 0;
-}
-
-}  // namespace shill.
diff --git a/kernel_bound_nlmessage.h b/kernel_bound_nlmessage.h
deleted file mode 100644
index 6a55986..0000000
--- a/kernel_bound_nlmessage.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// This code is derived from the 'iw' source code.  The copyright and license
-// of that code is as follows:
-//
-// Copyright (c) 2007, 2008  Johannes Berg
-// Copyright (c) 2007  Andy Lutomirski
-// Copyright (c) 2007  Mike Kershaw
-// Copyright (c) 2008-2009  Luis R. Rodriguez
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-#ifndef SHILL_KERNEL_BOUND_NLMESSAGE_H_
-#define SHILL_KERNEL_BOUND_NLMESSAGE_H_
-
-#include <base/basictypes.h>
-
-struct nl_msg;
-
-namespace shill {
-
-// TODO(wdg): eventually, KernelBoundNlMessage and UserBoundNlMessage should
-// be combined into a monolithic NlMessage.
-//
-// Provides a wrapper around a netlink message destined for kernel-space.
-class KernelBoundNlMessage {
- public:
-  // |command| is a type of command understood by the kernel, for instance:
-  // CTRL_CMD_GETFAMILY.
-  explicit KernelBoundNlMessage(uint8 command)
-      : command_(command),
-        message_(NULL) {}
-  virtual ~KernelBoundNlMessage();
-
-  // Non-trivial initialization.
-  bool Init();
-
-  // Add a netlink attribute to the message.
-  int AddAttribute(int attrtype, int attrlen, const void *data);
-
-  uint8 command() const { return command_; }
-  // TODO(wiley) It would be better if messages were bags of attributes which
-  //             the socket collapses into binary blobs at send time.
-  struct nl_msg *message() const { return message_; }
-  // Returns 0 when unsent, > 0 otherwise.
-  uint32 sequence_number() const;
-
- private:
-  uint8 command_;
-  // TODO(wiley) Rename to |raw_message_| (message.message() looks silly).
-  struct nl_msg *message_;
-
-  DISALLOW_COPY_AND_ASSIGN(KernelBoundNlMessage);
-};
-
-}  // namespace shill
-
-#endif  // SHILL_KERNEL_BOUND_NLMESSAGE_H_
diff --git a/mock_callback80211_object.h b/mock_callback80211_object.h
index 8a54d0e..4d9c33b 100644
--- a/mock_callback80211_object.h
+++ b/mock_callback80211_object.h
@@ -11,12 +11,12 @@
 
 namespace shill {
 
-class UserBoundNlMessage;
+class Nl80211Message;
 
 class MockCallback80211 : public Callback80211Object {
  public:
   MockCallback80211() {}
-  MOCK_METHOD1(Config80211MessageCallback, void(const UserBoundNlMessage &msg));
+  MOCK_METHOD1(Config80211MessageCallback, void(const Nl80211Message &msg));
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockCallback80211);
diff --git a/mock_nl80211_socket.h b/mock_nl80211_socket.h
index 51081d0..c30cd27 100644
--- a/mock_nl80211_socket.h
+++ b/mock_nl80211_socket.h
@@ -27,10 +27,9 @@
   using Nl80211Socket::SetNetlinkCallback;
   MOCK_METHOD2(SetNetlinkCallback, bool(nl_recvmsg_msg_cb_t on_netlink_data,
                                         void *callback_parameter));
-  MOCK_METHOD0(GetSequenceNumber, unsigned int());
 
-  virtual uint32 Send(KernelBoundNlMessage *message);
-
+  virtual uint32_t GetSequenceNumber();
+  virtual bool SendMessage(Nl80211Message *message);
   uint32 GetLastSequenceNumber() const { return sequence_number_; }
 
  private:
diff --git a/netlink_socket.cc b/netlink_socket.cc
index 87b200e..5ee9d34 100644
--- a/netlink_socket.cc
+++ b/netlink_socket.cc
@@ -37,8 +37,17 @@
 #include <netlink/netlink.h>
 
 #include <iomanip>
+#include <string>
+
+#include <base/eintr_wrapper.h>
+#include <base/logging.h>
+#include <base/stringprintf.h>
 
 #include "shill/logging.h"
+#include "shill/nl80211_message.h"
+
+using base::StringAppendF;
+using std::string;
 
 namespace shill {
 
@@ -111,46 +120,40 @@
   return true;
 }
 
-uint32 NetlinkSocket::Send(struct nl_msg *message,
-                           uint8 command,
-                           int32 family_id) {
+bool NetlinkSocket::SendMessage(Nl80211Message *message) {
   if (!message) {
     LOG(ERROR) << "NULL |message|.";
-    return 0;
+    return false;
   }
 
   if (!nl_sock_) {
     LOG(ERROR) << "Need to initialize the socket first.";
-    return 0;
+    return false;
   }
 
-  // Parameters to genlmsg_put:
-  //  @message: a pointer to a struct nl_msg *message.
-  //  @pid: netlink pid the message is addressed to.
-  //  @seq: sequence number.
-  //  @family: netlink socket family (NETLINK_GENERIC for us)
-  //  @flags netlink message flags.
-  //  @hdrlen: Length of a user header (which we don't use)
-  //  @cmd: netlink command.
-  //  @version: version of communication protocol.
-  // genlmsg_put returns a void * pointing to the user header but we don't
-  // want to encourage its use outside of this object.
+  ByteString out_msg = message->Encode(family_id());
 
-  uint32 sequence_number = GetSequenceNumber();
-  if (genlmsg_put(message, NL_AUTO_PID, sequence_number, family_id,
-                  0, 0, command, 0) == NULL) {
-    LOG(ERROR) << "genlmsg_put returned a NULL pointer.";
-    return 0;
+  if (SLOG_IS_ON(WiFi, 6)) {
+    SLOG(WiFi, 6) << "NL Message " << message->sequence_number() << " ===>";
+    SLOG(WiFi, 6) << "  Sending (" << out_msg.GetLength() << " bytes) : "
+              << message->GenericToString();
+
+    const unsigned char *out_data = out_msg.GetConstData();
+    string output;
+    for (size_t i = 0; i < out_msg.GetLength(); ++i) {
+      StringAppendF(&output, " %02x", out_data[i]);
+    }
+    SLOG(WiFi, 6) << output;
   }
 
-  SLOG(WiFi, 6) << "NL Message " << sequence_number << " ===>";
-
-  int result = nl_send_auto_complete(nl_sock_, message);
-  if (result < 0) {
-    LOG(ERROR) << "Failed call to 'nl_send_auto_complete': " << result;
-    return 0;
+  int result = HANDLE_EINTR(send(GetFd(), out_msg.GetConstData(),
+                                 out_msg.GetLength(), 0));
+  if (!result) {
+    PLOG(ERROR) << "Send failed.";
+    return false;
   }
-  return sequence_number;
+
+  return true;
 }
 
 
diff --git a/netlink_socket.h b/netlink_socket.h
index aad3d65..5b89400 100644
--- a/netlink_socket.h
+++ b/netlink_socket.h
@@ -43,6 +43,8 @@
 
 namespace shill {
 
+class Nl80211Message;
+
 // Provides an abstraction to a netlink socket.  See
 // http://www.infradead.org/~tgr/libnl/ for documentation on how netlink
 // sockets work.
@@ -102,21 +104,24 @@
 
   // Get the next message sequence number for this socket.  Disallow zero so
   // that we can use that as the 'broadcast' sequence number.
-  virtual unsigned int GetSequenceNumber();
+  virtual uint32_t GetSequenceNumber();
 
   // This method is called |callback_function| to differentiate it from the
-  // 'callback' method in KernelBoundNlMessage since they return different
+  // 'callback' method in Nl80211Message since they return different
   // types.
   virtual bool SetNetlinkCallback(nl_recvmsg_msg_cb_t on_netlink_data,
                                   void *callback_parameter);
 
+  // Returns the value returned by the 'genl_ctrl_resolve' call.
+  virtual int family_id() const = 0;
+
   // Returns the family name of the socket created by this type of object.
   virtual std::string GetSocketFamilyName() const = 0;
 
- protected:
-  // Send a message, returns 0 on error, or the sequence number (> 0).
-  uint32 Send(struct nl_msg *message, uint8 command, int32 family_id);
+  // Sends a message, returns true if successful.
+  virtual bool SendMessage(Nl80211Message *message);
 
+ protected:
   struct nl_sock *GetNlSock() { return nl_sock_; }
 
  private:
diff --git a/nl80211_attribute.cc b/nl80211_attribute.cc
index a8338ff..e108524 100644
--- a/nl80211_attribute.cc
+++ b/nl80211_attribute.cc
@@ -220,6 +220,17 @@
   return output;
 }
 
+ByteString Nl80211Attribute::EncodeGeneric(const unsigned char *data,
+                                           int bytes) const {
+  nlattr header;
+  header.nla_type = id();
+  header.nla_len = nla_attr_size(bytes);
+  ByteString result(reinterpret_cast<unsigned char *>(&header), sizeof(header));
+  result.Append(ByteString(data, bytes));
+  result.Resize(nla_total_size(bytes));  // Add padding.
+  return result;
+}
+
 // Nl80211U8Attribute
 
 const char Nl80211U8Attribute::kMyTypeString[] = "uint8_t";
@@ -261,6 +272,11 @@
   return true;
 }
 
+ByteString Nl80211U8Attribute::Encode() const {
+  return Nl80211Attribute::EncodeGeneric(
+      reinterpret_cast<const unsigned char *>(&value_), sizeof(value_));
+}
+
 
 // Nl80211U16Attribute
 
@@ -303,6 +319,11 @@
   return true;
 }
 
+ByteString Nl80211U16Attribute::Encode() const {
+  return Nl80211Attribute::EncodeGeneric(
+      reinterpret_cast<const unsigned char *>(&value_), sizeof(value_));
+}
+
 // Nl80211U32Attribute::
 
 const char Nl80211U32Attribute::kMyTypeString[] = "uint32_t";
@@ -344,6 +365,11 @@
   return true;
 }
 
+ByteString Nl80211U32Attribute::Encode() const {
+  return Nl80211Attribute::EncodeGeneric(
+      reinterpret_cast<const unsigned char *>(&value_), sizeof(value_));
+}
+
 // Nl80211U64Attribute
 
 const char Nl80211U64Attribute::kMyTypeString[] = "uint64_t";
@@ -385,6 +411,11 @@
   return true;
 }
 
+ByteString Nl80211U64Attribute::Encode() const {
+  return Nl80211Attribute::EncodeGeneric(
+      reinterpret_cast<const unsigned char *>(&value_), sizeof(value_));
+}
+
 // Nl80211FlagAttribute
 
 const char Nl80211FlagAttribute::kMyTypeString[] = "flag";
@@ -427,6 +458,11 @@
   return true;
 }
 
+ByteString Nl80211FlagAttribute::Encode() const {
+  return Nl80211Attribute::EncodeGeneric(
+      reinterpret_cast<const unsigned char *>(&value_), sizeof(value_));
+}
+
 // Nl80211StringAttribute
 
 const char Nl80211StringAttribute::kMyTypeString[] = "string";
@@ -468,6 +504,11 @@
   return true;
 }
 
+ByteString Nl80211StringAttribute::Encode() const {
+  return Nl80211Attribute::EncodeGeneric(
+      reinterpret_cast<const unsigned char *>(value_.c_str()), value_.size());
+}
+
 // Nl80211NestedAttribute
 const char Nl80211NestedAttribute::kMyTypeString[] = "nested";
 const Nl80211Attribute::Type Nl80211NestedAttribute::kType =
diff --git a/nl80211_attribute.h b/nl80211_attribute.h
index 8e3095d..8d99983 100644
--- a/nl80211_attribute.h
+++ b/nl80211_attribute.h
@@ -22,8 +22,6 @@
 
 namespace shill {
 
-class AttributeList;
-
 // Nl80211Attribute is an abstract base class that describes an attribute in a
 // netlink-80211 message.  Child classes are type-specific and will define
 // Get*Value and Set*Value methods (where * is the type).  A second-level of
@@ -57,7 +55,7 @@
   // raw nlattr data.
   static Nl80211Attribute *NewFromName(nl80211_attrs id);
 
-  // Accessors for the attribute's id and type information.
+  // Accessors for the attribute's id and datatype information.
   int id() const { return id_; }
   virtual const char *id_string() const { return id_string_; }
   Type datatype() const { return datatype_; }
@@ -96,13 +94,18 @@
   virtual bool GetRawValue(ByteString *value) const;
 
   // Fill a string with characters that represents the value of the attribute.
-  // If no attribute is found or if the type isn't trivially stringizable,
+  // If no attribute is found or if the datatype isn't trivially stringizable,
   // this method returns 'false' and |value| remains unchanged.
   virtual bool ToString(std::string *value) const = 0;
 
   // Writes the raw attribute data to a string.  For debug.
   std::string RawToString() const;
 
+  // Encodes the attribute suitably for the attributes in the payload portion
+  // of a netlink message suitable for Sockets::Send.  Return value is empty on
+  // failure.
+  virtual ByteString Encode() const = 0;
+
   // Note that |nla_get_*| don't change their arguments but don't declare
   // themselves as 'const', either.  These methods wrap the const castness.
   static char *NlaGetString(const nlattr *input) {
@@ -122,6 +125,11 @@
   }
 
  protected:
+  // Encodes the attribute suitably for the attributes in the payload portion
+  // of a netlink message suitable for Sockets::Send.  Return value is empty on
+  // failure.
+  virtual ByteString EncodeGeneric(const unsigned char *data, int bytes) const;
+
   // Raw data corresponding to the value in any of the child classes.
   // TODO(wdg): When 'data()' is removed, move this to the Nl80211RawAttribute
   // class.
@@ -146,6 +154,7 @@
   bool GetU8Value(uint8_t *value) const;
   bool SetU8Value(uint8_t new_value);
   bool ToString(std::string *value) const;
+  virtual ByteString Encode() const;
 
  private:
   uint8_t value_;
@@ -177,6 +186,7 @@
   bool GetU16Value(uint16_t *value) const;
   bool SetU16Value(uint16_t new_value);
   bool ToString(std::string *value) const;
+  virtual ByteString Encode() const;
 
  private:
   uint16_t value_;
@@ -208,6 +218,7 @@
   bool GetU32Value(uint32_t *value) const;
   bool SetU32Value(uint32_t new_value);
   bool ToString(std::string *value) const;
+  virtual ByteString Encode() const;
 
  private:
   uint32_t value_;
@@ -274,6 +285,7 @@
   bool GetU64Value(uint64_t *value) const;
   bool SetU64Value(uint64_t new_value);
   bool ToString(std::string *value) const;
+  virtual ByteString Encode() const;
 
  private:
   uint64_t value_;
@@ -298,6 +310,7 @@
   bool GetFlagValue(bool *value) const;
   bool SetFlagValue(bool new_value);
   bool ToString(std::string *value) const;
+  virtual ByteString Encode() const;
 
  private:
   bool value_;
@@ -338,6 +351,7 @@
   bool GetStringValue(std::string *value) const;
   bool SetStringValue(const std::string new_value);
   bool ToString(std::string *value) const;
+  virtual ByteString Encode() const;
 
  private:
   std::string value_;
@@ -364,7 +378,6 @@
   static const char kMyTypeString[];
   static const Type kType;
   Nl80211NestedAttribute(int id, const char *id_string);
-  virtual ~Nl80211NestedAttribute() {}
   bool InitFromNlAttr(const nlattr *data) {
     LOG(FATAL) << "Try initializing a _specific_ nested type, instead.";
     return false;
@@ -373,6 +386,9 @@
   bool ToString(std::string *value) const {
     return false;  // TODO(wdg):
   }
+  virtual ByteString Encode() const {
+    return ByteString();  // TODO(wdg): Actually encode the attribute.
+  }
 
  protected:
   AttributeList value_;
@@ -416,6 +432,9 @@
   // is intended for building kernel-bound messages and shouldn't be used with
   // raw data.
   bool ToString(std::string *value) const;
+  virtual ByteString Encode() const {
+    return ByteString();  // TODO(wdg): Actually encode the attribute.
+  }
 };
 
 class Nl80211AttributeFrame : public Nl80211RawAttribute {
diff --git a/user_bound_nlmessage.cc b/nl80211_message.cc
similarity index 92%
rename from user_bound_nlmessage.cc
rename to nl80211_message.cc
index 9afaeaf..3fb4826 100644
--- a/user_bound_nlmessage.cc
+++ b/nl80211_message.cc
@@ -22,7 +22,7 @@
 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-#include "shill/user_bound_nlmessage.h"
+#include "shill/nl80211_message.h"
 
 #include <ctype.h>
 #include <endian.h>
@@ -47,6 +47,7 @@
 #include "shill/attribute_list.h"
 #include "shill/ieee80211.h"
 #include "shill/logging.h"
+#include "shill/netlink_socket.h"
 #include "shill/nl80211_attribute.h"
 #include "shill/scope_logger.h"
 
@@ -60,19 +61,19 @@
 namespace shill {
 
 namespace {
-LazyInstance<UserBoundNlMessageDataCollector> g_datacollector =
+LazyInstance<Nl80211MessageDataCollector> g_datacollector =
     LAZY_INSTANCE_INITIALIZER;
 }  // namespace
 
-const char UserBoundNlMessage::kBogusMacAddress[]="XX:XX:XX:XX:XX:XX";
+const char Nl80211Message::kBogusMacAddress[]="XX:XX:XX:XX:XX:XX";
 
 const uint8_t Nl80211Frame::kMinimumFrameByteCount = 26;
 const uint8_t Nl80211Frame::kFrameTypeMask = 0xfc;
 
-const uint32_t UserBoundNlMessage::kIllegalMessage = 0xFFFFFFFF;
-const unsigned int UserBoundNlMessage::kEthernetAddressBytes = 6;
-map<uint16_t, string> *UserBoundNlMessage::reason_code_string_ = NULL;
-map<uint16_t, string> *UserBoundNlMessage::status_code_string_ = NULL;
+const uint32_t Nl80211Message::kIllegalMessage = 0;
+const unsigned int Nl80211Message::kEthernetAddressBytes = 6;
+map<uint16_t, string> *Nl80211Message::reason_code_string_ = NULL;
+map<uint16_t, string> *Nl80211Message::status_code_string_ = NULL;
 
 // The nl messages look like this:
 //
@@ -99,11 +100,12 @@
 //       +-- msg = nlmsg_hdr(raw_message)
 
 //
-// UserBoundNlMessage
+// Nl80211Message
 //
 
-bool UserBoundNlMessage::Init(nlattr *tb[NL80211_ATTR_MAX + 1],
-                              nlmsghdr *msg) {
+// TODO(wdg): do the nlattr parsing inside here.
+bool Nl80211Message::Init(nlattr *tb[NL80211_ATTR_MAX + 1],
+                          nlmsghdr *msg) {
   if (!tb) {
     LOG(ERROR) << "Null |tb| parameter";
     return false;
@@ -111,7 +113,7 @@
 
   message_ = msg;
 
-  SLOG(WiFi, 6) << "NL Message " << GetId() << " <===";
+  SLOG(WiFi, 6) << "NL Message " << sequence_number() << " <===";
 
   for (int i = 0; i < NL80211_ATTR_MAX + 1; ++i) {
     if (tb[i]) {
@@ -317,17 +319,9 @@
   return true;
 }
 
-uint32_t UserBoundNlMessage::GetId() const {
-  if (!message_) {
-    return kIllegalMessage;
-  }
-  return message_->nlmsg_seq;
-}
-
-
 // Helper function to provide a string for a MAC address.
-bool UserBoundNlMessage::GetMacAttributeString(nl80211_attrs id,
-                                               string *value) const {
+bool Nl80211Message::GetMacAttributeString(nl80211_attrs id,
+                                           string *value) const {
   if (!value) {
     LOG(ERROR) << "Null |value| parameter";
     return false;
@@ -344,7 +338,7 @@
 }
 
 // Helper function to provide a string for NL80211_ATTR_SCAN_FREQUENCIES.
-bool UserBoundNlMessage::GetScanFrequenciesAttribute(
+bool Nl80211Message::GetScanFrequenciesAttribute(
     nl80211_attrs id, vector<uint32_t> *value) const {
   if (!value) {
     LOG(ERROR) << "Null |value| parameter";
@@ -370,8 +364,8 @@
 }
 
 // Helper function to provide a string for NL80211_ATTR_SCAN_SSIDS.
-bool UserBoundNlMessage::GetScanSsidsAttribute(nl80211_attrs id,
-                                               vector<string> *value) const {
+bool Nl80211Message::GetScanSsidsAttribute(
+    nl80211_attrs id, vector<string> *value) const {
   if (!value) {
     LOG(ERROR) << "Null |value| parameter";
     return false;
@@ -398,7 +392,7 @@
 
 // Protected members.
 
-string UserBoundNlMessage::GetHeaderString() const {
+string Nl80211Message::GetHeaderString() const {
   char ifname[IF_NAMESIZE] = "";
   uint32_t ifindex = UINT32_MAX;
   bool ifindex_exists = attributes().GetU32AttributeValue(NL80211_ATTR_IFINDEX,
@@ -423,7 +417,7 @@
   return output;
 }
 
-string UserBoundNlMessage::StringFromFrame(nl80211_attrs attr_name) const {
+string Nl80211Message::StringFromFrame(nl80211_attrs attr_name) const {
   string output;
   ByteString frame_data;
   if (attributes().GetRawAttributeValue(attr_name,
@@ -438,7 +432,7 @@
 }
 
 // static
-string UserBoundNlMessage::StringFromKeyType(nl80211_key_type key_type) {
+string Nl80211Message::StringFromKeyType(nl80211_key_type key_type) {
   switch (key_type) {
   case NL80211_KEYTYPE_GROUP:
     return "Group";
@@ -452,7 +446,7 @@
 }
 
 // static
-string UserBoundNlMessage::StringFromMacAddress(const uint8_t *arg) {
+string Nl80211Message::StringFromMacAddress(const uint8_t *arg) {
   string output;
 
   if (!arg) {
@@ -469,7 +463,7 @@
 }
 
 // static
-string UserBoundNlMessage::StringFromRegInitiator(__u8 initiator) {
+string Nl80211Message::StringFromRegInitiator(__u8 initiator) {
   switch (initiator) {
   case NL80211_REGDOM_SET_BY_CORE:
     return "the wireless core upon initialization";
@@ -485,7 +479,7 @@
 }
 
 // static
-string UserBoundNlMessage::StringFromSsid(const uint8_t len,
+string Nl80211Message::StringFromSsid(const uint8_t len,
                                           const uint8_t *data) {
   string output;
   if (!data) {
@@ -507,7 +501,7 @@
 }
 
 // static
-string UserBoundNlMessage::StringFromReason(uint16_t status) {
+string Nl80211Message::StringFromReason(uint16_t status) {
   map<uint16_t, string>::const_iterator match;
   match = reason_code_string_->find(status);
   if (match == reason_code_string_->end()) {
@@ -523,7 +517,7 @@
 }
 
 // static
-string UserBoundNlMessage::StringFromStatus(uint16_t status) {
+string Nl80211Message::StringFromStatus(uint16_t status) {
   map<uint16_t, string>::const_iterator match;
   match = status_code_string_->find(status);
   if (match == status_code_string_->end()) {
@@ -538,14 +532,55 @@
   return match->second;
 }
 
-string UserBoundNlMessage::GenericToString() const {
+string Nl80211Message::GenericToString() const {
   string output;
-  StringAppendF(&output, "Received %s (%d)\n",
+  StringAppendF(&output, "Message %s (%d)\n",
                 message_type_string(), message_type());
   StringAppendF(&output, "%s", attributes_.ToString().c_str());
   return output;
 }
 
+ByteString Nl80211Message::Encode(uint16_t nlmsg_type) const {
+  // 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();
+
+  // Build genl message header.
+  genlmsghdr genl_header;
+  size_t genlmsghdr_with_pad = NLMSG_ALIGN(sizeof(genl_header));
+  header.nlmsg_len += genlmsghdr_with_pad;
+  genl_header.cmd = message_type();
+  genl_header.version = 1;
+  genl_header.reserved = 0;
+
+  // Assemble attributes (padding is included by AttributeList::Encode).
+  ByteString attributes = attributes_.Encode();
+  header.nlmsg_len += attributes.GetLength();
+
+  // Now that we know the total message size, build the output ByteString.
+  ByteString result;
+
+  // Netlink header + pad.
+  result.Append(ByteString(reinterpret_cast<unsigned char *>(&header),
+                           sizeof(header)));
+  result.Resize(nlmsghdr_with_pad);  // Zero-fill pad space (if any).
+
+  // Genl message header + pad.
+  result.Append(ByteString(reinterpret_cast<unsigned char *>(&genl_header),
+                           sizeof(genl_header)));
+  result.Resize(nlmsghdr_with_pad + genlmsghdr_with_pad);  // Zero-fill.
+
+  // Attributes including pad.
+  result.Append(attributes);
+
+  return result;
+}
+
 Nl80211Frame::Nl80211Frame(const ByteString &raw_frame)
   : frame_type_(kIllegalFrameType), reason_(UINT16_MAX), status_(UINT16_MAX),
     frame_(raw_frame) {
@@ -556,8 +591,8 @@
   // Now, let's populate the other stuff.
   if (frame_.GetLength() >= kMinimumFrameByteCount) {
     mac_from_ =
-        UserBoundNlMessage::StringFromMacAddress(&frame->destination_mac[0]);
-    mac_to_ = UserBoundNlMessage::StringFromMacAddress(&frame->source_mac[0]);
+        Nl80211Message::StringFromMacAddress(&frame->destination_mac[0]);
+    mac_to_ = Nl80211Message::StringFromMacAddress(&frame->source_mac[0]);
     frame_type_ = frame->frame_control & kFrameTypeMask;
 
     switch (frame_type_) {
@@ -601,28 +636,28 @@
     case kAssocResponseFrameType:
       StringAppendF(output, "; AssocResponse status: %u: %s",
                     status_,
-                    UserBoundNlMessage::StringFromStatus(status_).c_str());
+                    Nl80211Message::StringFromStatus(status_).c_str());
       break;
     case kReassocResponseFrameType:
       StringAppendF(output, "; ReassocResponse status: %u: %s",
                     status_,
-                    UserBoundNlMessage::StringFromStatus(status_).c_str());
+                    Nl80211Message::StringFromStatus(status_).c_str());
       break;
     case kAuthFrameType:
       StringAppendF(output, "; Auth status: %u: %s",
                     status_,
-                    UserBoundNlMessage::StringFromStatus(status_).c_str());
+                    Nl80211Message::StringFromStatus(status_).c_str());
       break;
 
     case kDisassocFrameType:
       StringAppendF(output, "; Disassoc reason %u: %s",
                     reason_,
-                    UserBoundNlMessage::StringFromReason(reason_).c_str());
+                    Nl80211Message::StringFromReason(reason_).c_str());
       break;
     case kDeauthFrameType:
       StringAppendF(output, "; Deauth reason %u: %s",
                     reason_,
-                    UserBoundNlMessage::StringFromReason(reason_).c_str());
+                    Nl80211Message::StringFromReason(reason_).c_str());
       break;
 
     default:
@@ -646,7 +681,7 @@
 
 
 //
-// Specific UserBoundNlMessage types.
+// Specific Nl80211Message types.
 //
 
 const uint8_t AssociateMessage::kCommand = NL80211_CMD_ASSOCIATE;
@@ -820,7 +855,7 @@
     ByteString rawdata;
     if (attributes().GetRawAttributeValue(NL80211_ATTR_KEY_SEQ,
                                           &rawdata) &&
-        rawdata.GetLength() == UserBoundNlMessage::kEthernetAddressBytes) {
+        rawdata.GetLength() == Nl80211Message::kEthernetAddressBytes) {
       const unsigned char *seq = rawdata.GetConstData();
       StringAppendF(&output, " seq=%02x%02x%02x%02x%02x%02x",
                     seq[0], seq[1], seq[2], seq[3], seq[4], seq[5]);
@@ -1268,13 +1303,14 @@
 // Factory class.
 //
 
-UserBoundNlMessage *UserBoundNlMessageFactory::CreateMessage(nlmsghdr *msg) {
+Nl80211Message *Nl80211MessageFactory::CreateMessage(nlmsghdr *msg) {
   if (!msg) {
     LOG(ERROR) << "NULL |msg| parameter";
     return NULL;
   }
 
-  scoped_ptr<UserBoundNlMessage> message;
+  scoped_ptr<Nl80211Message> message;
+
   genlmsghdr *gnlh =
       reinterpret_cast<genlmsghdr *>(nlmsg_data(msg));
 
@@ -1353,12 +1389,12 @@
   return message.release();
 }
 
-UserBoundNlMessageDataCollector *
-    UserBoundNlMessageDataCollector::GetInstance() {
+Nl80211MessageDataCollector *
+    Nl80211MessageDataCollector::GetInstance() {
   return g_datacollector.Pointer();
 }
 
-UserBoundNlMessageDataCollector::UserBoundNlMessageDataCollector() {
+Nl80211MessageDataCollector::Nl80211MessageDataCollector() {
   need_to_print[NL80211_ATTR_PMKSA_CANDIDATE] = true;
   need_to_print[NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL] = true;
   need_to_print[NL80211_CMD_DEL_STATION] = true;
@@ -1375,8 +1411,8 @@
   need_to_print[NL80211_CMD_UNPROT_DISASSOCIATE] = true;
 }
 
-void UserBoundNlMessageDataCollector::CollectDebugData(
-    const UserBoundNlMessage &message, nlmsghdr *msg) {
+void Nl80211MessageDataCollector::CollectDebugData(
+    const Nl80211Message &message, nlmsghdr *msg) {
   if (!msg) {
     LOG(ERROR) << "NULL |msg| parameter";
     return;
diff --git a/user_bound_nlmessage.h b/nl80211_message.h
similarity index 68%
rename from user_bound_nlmessage.h
rename to nl80211_message.h
index cd6dbc0..32d51ea 100644
--- a/user_bound_nlmessage.h
+++ b/nl80211_message.h
@@ -26,22 +26,25 @@
 namespace shill {
 
 // Class for messages received from libnl.
-class UserBoundNlMessage {
+class Nl80211Message {
  public:
   static const unsigned int kEthernetAddressBytes;
   static const char kBogusMacAddress[];
 
-  UserBoundNlMessage(uint8 message_type, const char *message_type_string)
+  Nl80211Message(uint8 message_type, const char *message_type_string)
       : message_(NULL),
         message_type_(message_type),
-        message_type_string_(message_type_string) {}
-  virtual ~UserBoundNlMessage() {}
+        message_type_string_(message_type_string),
+        sequence_number_(kIllegalMessage) {}
+  virtual ~Nl80211Message() {}
 
-  // Non-trivial initialization.
+  // TODO(wdg): Change to |InitFromNlmsg|.
+  // Initializes the message with bytes from the kernel.
   virtual bool Init(nlattr *tb[NL80211_ATTR_MAX + 1], nlmsghdr *msg);
 
-  // Message ID is equivalent to the message's sequence number.
-  uint32_t GetId() const;
+  uint32_t sequence_number() const { return sequence_number_; }
+
+  void set_sequence_number(uint32_t seq) { sequence_number_ = seq; }
 
   const AttributeList &attributes() const { return attributes_; }
 
@@ -74,14 +77,27 @@
   static std::string StringFromReason(uint16_t reason);
   static std::string StringFromStatus(uint16_t status);
 
+  // Returns a string that describes the message in terms of its attributes.
+  // For example, a trigger scan message might look like:
+  // Received _NL80211_CMD_TRIGGER_SCAN (33)
+  //    Attr:NL80211_ATTR_WIPHY=0 Type:uint32_t
+  //    Attr:NL80211_ATTR_IFINDEX=2 Type:uint32_t
+  //    Attr:NL80211_ATTR_SCAN_FREQUENCIES=296 bytes: 0x2c [...]
   std::string GenericToString() const;
 
-  // Returns a string that describes this message.
+  // Returns a string that describes this message in a message-type-specific
+  // way.  For example, a trigger scan message might look like:
+  // @wlan0 (phy #0): scan started; frequencies: 2412, [...] 5825, ; SSIDs: "",
   virtual std::string ToString() const { return GetHeaderString(); }
 
   uint8 message_type() const { return message_type_; }
   const char *message_type_string() const { return message_type_string_; }
 
+  // Returns a netlink message suitable for Sockets::Send.  Return value is
+  // empty on failure.  |nlmsg_type| needs to be the family id returned by
+  // |genl_ctrl_resolve|.
+  ByteString Encode(uint16_t nlmsg_type) const;
+
  protected:
   // Returns a string that should precede all user-bound message strings.
   virtual std::string GetHeaderString() const;
@@ -112,10 +128,11 @@
   const char *message_type_string_;
   static std::map<uint16_t, std::string> *reason_code_string_;
   static std::map<uint16_t, std::string> *status_code_string_;
+  uint32_t sequence_number_;
 
   AttributeList attributes_;
 
-  DISALLOW_COPY_AND_ASSIGN(UserBoundNlMessage);
+  DISALLOW_COPY_AND_ASSIGN(Nl80211Message);
 };
 
 class Nl80211Frame {
@@ -152,15 +169,15 @@
 };
 
 //
-// Specific UserBoundNlMessage types.
+// Specific Nl80211Message types.
 //
 
-class AssociateMessage : public UserBoundNlMessage {
+class AssociateMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  AssociateMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  AssociateMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -169,12 +186,12 @@
 };
 
 
-class AuthenticateMessage : public UserBoundNlMessage {
+class AuthenticateMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  AuthenticateMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  AuthenticateMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -183,13 +200,13 @@
 };
 
 
-class CancelRemainOnChannelMessage : public UserBoundNlMessage {
+class CancelRemainOnChannelMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
   CancelRemainOnChannelMessage()
-      : UserBoundNlMessage(kCommand, kCommandString) {}
+      : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -198,12 +215,12 @@
 };
 
 
-class ConnectMessage : public UserBoundNlMessage {
+class ConnectMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  ConnectMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  ConnectMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -212,12 +229,12 @@
 };
 
 
-class DeauthenticateMessage : public UserBoundNlMessage {
+class DeauthenticateMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  DeauthenticateMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  DeauthenticateMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -226,12 +243,12 @@
 };
 
 
-class DeleteStationMessage : public UserBoundNlMessage {
+class DeleteStationMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  DeleteStationMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  DeleteStationMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -240,12 +257,12 @@
 };
 
 
-class DisassociateMessage : public UserBoundNlMessage {
+class DisassociateMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  DisassociateMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  DisassociateMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -254,12 +271,12 @@
 };
 
 
-class DisconnectMessage : public UserBoundNlMessage {
+class DisconnectMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  DisconnectMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  DisconnectMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -268,12 +285,12 @@
 };
 
 
-class FrameTxStatusMessage : public UserBoundNlMessage {
+class FrameTxStatusMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  FrameTxStatusMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  FrameTxStatusMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -282,12 +299,12 @@
 };
 
 
-class JoinIbssMessage : public UserBoundNlMessage {
+class JoinIbssMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  JoinIbssMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  JoinIbssMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -296,12 +313,12 @@
 };
 
 
-class MichaelMicFailureMessage : public UserBoundNlMessage {
+class MichaelMicFailureMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  MichaelMicFailureMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  MichaelMicFailureMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -310,12 +327,12 @@
 };
 
 
-class NewScanResultsMessage : public UserBoundNlMessage {
+class NewScanResultsMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  NewScanResultsMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  NewScanResultsMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -324,12 +341,12 @@
 };
 
 
-class NewStationMessage : public UserBoundNlMessage {
+class NewStationMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  NewStationMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  NewStationMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -338,12 +355,12 @@
 };
 
 
-class NewWifiMessage : public UserBoundNlMessage {
+class NewWifiMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  NewWifiMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  NewWifiMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -352,12 +369,12 @@
 };
 
 
-class NotifyCqmMessage : public UserBoundNlMessage {
+class NotifyCqmMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  NotifyCqmMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  NotifyCqmMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -366,12 +383,12 @@
 };
 
 
-class PmksaCandidateMessage : public UserBoundNlMessage {
+class PmksaCandidateMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  PmksaCandidateMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  PmksaCandidateMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -380,12 +397,12 @@
 };
 
 
-class RegBeaconHintMessage : public UserBoundNlMessage {
+class RegBeaconHintMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  RegBeaconHintMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  RegBeaconHintMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -408,12 +425,12 @@
 };
 
 
-class RegChangeMessage : public UserBoundNlMessage {
+class RegChangeMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  RegChangeMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  RegChangeMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -422,12 +439,12 @@
 };
 
 
-class RemainOnChannelMessage : public UserBoundNlMessage {
+class RemainOnChannelMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  RemainOnChannelMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  RemainOnChannelMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -436,12 +453,12 @@
 };
 
 
-class RoamMessage : public UserBoundNlMessage {
+class RoamMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  RoamMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  RoamMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -450,12 +467,12 @@
 };
 
 
-class ScanAbortedMessage : public UserBoundNlMessage {
+class ScanAbortedMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  ScanAbortedMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  ScanAbortedMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -464,12 +481,12 @@
 };
 
 
-class TriggerScanMessage : public UserBoundNlMessage {
+class TriggerScanMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  TriggerScanMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  TriggerScanMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -478,10 +495,10 @@
 };
 
 
-class UnknownMessage : public UserBoundNlMessage {
+class UnknownMessage : public Nl80211Message {
  public:
   explicit UnknownMessage(uint8_t command)
-      : UserBoundNlMessage(command, kCommandString),
+      : Nl80211Message(command, kCommandString),
         command_(command) {}
 
   static const uint8_t kCommand;
@@ -496,13 +513,13 @@
 };
 
 
-class UnprotDeauthenticateMessage : public UserBoundNlMessage {
+class UnprotDeauthenticateMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
   UnprotDeauthenticateMessage()
-      : UserBoundNlMessage(kCommand, kCommandString) {}
+      : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -511,12 +528,12 @@
 };
 
 
-class UnprotDisassociateMessage : public UserBoundNlMessage {
+class UnprotDisassociateMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
   static const char kCommandString[];
 
-  UnprotDisassociateMessage() : UserBoundNlMessage(kCommand, kCommandString) {}
+  UnprotDisassociateMessage() : Nl80211Message(kCommand, kCommandString) {}
 
   virtual std::string ToString() const;
 
@@ -529,37 +546,38 @@
 // Factory class.
 //
 
-class UserBoundNlMessageFactory {
+class Nl80211MessageFactory {
  public:
   // Ownership of the message is passed to the caller and, as such, he should
   // delete it.
-  static UserBoundNlMessage *CreateMessage(nlmsghdr *msg);
+  static Nl80211Message *CreateMessage(nlmsghdr *msg);
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(UserBoundNlMessageFactory);
+  DISALLOW_COPY_AND_ASSIGN(Nl80211MessageFactory);
 };
 
 
-// UserBoundNlMessageDataCollector - this class is used to collect data to be
+// Nl80211MessageDataCollector - this class is used to collect data to be
 // used for unit tests.  It is only invoked in this case.
 
-class UserBoundNlMessageDataCollector {
+class Nl80211MessageDataCollector {
  public:
-  // This is a singleton -- use Config80211::GetInstance()->Foo()
-  static UserBoundNlMessageDataCollector *GetInstance();
+  static Nl80211MessageDataCollector *GetInstance();
 
-  void CollectDebugData(const UserBoundNlMessage &message, nlmsghdr *msg);
+  void CollectDebugData(const Nl80211Message &message, nlmsghdr *msg);
 
  protected:
   friend struct
-      base::DefaultLazyInstanceTraits<UserBoundNlMessageDataCollector>;
+      base::DefaultLazyInstanceTraits<Nl80211MessageDataCollector>;
 
-  explicit UserBoundNlMessageDataCollector();
+  explicit Nl80211MessageDataCollector();
 
  private:
   // In order to limit the output from this class, I keep track of types I
   // haven't yet printed.
   std::map<uint8_t, bool> need_to_print;
+
+  DISALLOW_COPY_AND_ASSIGN(Nl80211MessageDataCollector);
 };
 
 }  // namespace shill
diff --git a/nl80211_socket.cc b/nl80211_socket.cc
index d2c7fb0..810bb7f 100644
--- a/nl80211_socket.cc
+++ b/nl80211_socket.cc
@@ -39,10 +39,9 @@
 #include <sstream>
 #include <string>
 
-#include "shill/kernel_bound_nlmessage.h"
 #include "shill/logging.h"
 #include "shill/netlink_socket.h"
-#include "shill/user_bound_nlmessage.h"
+#include "shill/nl80211_message.h"
 
 using std::string;
 
@@ -56,9 +55,9 @@
     return false;
   }
 
-  nl80211_id_ = genl_ctrl_resolve(GetNlSock(), "nlctrl");
-  if (nl80211_id_ < 0) {
-    LOG(ERROR) << "nl80211 not found.";
+  family_id_ = genl_ctrl_resolve(GetNlSock(), kSocketFamilyName);
+  if (family_id_ < 0) {
+    LOG(ERROR) << kSocketFamilyName << " not found.";
     return false;
   }
 
@@ -83,11 +82,4 @@
   return true;
 }
 
-uint32 Nl80211Socket::Send(KernelBoundNlMessage *message) {
-  CHECK(message);
-  return NetlinkSocket::Send(message->message(),
-                             message->command(),
-                             GetFamilyId());
-}
-
 }  // namespace shill
diff --git a/nl80211_socket.h b/nl80211_socket.h
index f7d4408..9bfa525 100644
--- a/nl80211_socket.h
+++ b/nl80211_socket.h
@@ -25,16 +25,13 @@
 #ifndef SHILL_NL80211_SOCKET_H_
 #define SHILL_NL80211_SOCKET_H_
 
-#include <iomanip>
 #include <string>
 
 #include <linux/nl80211.h>
 
 #include <base/basictypes.h>
-#include <base/bind.h>
 
 #include "shill/netlink_socket.h"
-#include "shill/kernel_bound_nlmessage.h"
 
 struct nl_msg;
 struct sockaddr_nl;
@@ -46,7 +43,7 @@
 // utilizing a netlink socket.
 class Nl80211Socket : public NetlinkSocket {
  public:
-  Nl80211Socket() : nl80211_id_(-1) {}
+  Nl80211Socket() : family_id_(-1) {}
   virtual ~Nl80211Socket() {}
 
   // Perform non-trivial initialization.
@@ -59,21 +56,19 @@
   virtual bool AddGroupMembership(const std::string &group_name);
 
   // Returns the value returned by the 'genl_ctrl_resolve' call.
-  int GetFamilyId() const { return nl80211_id_; }
+  int family_id() const { return family_id_; }
 
   // Gets the name of the socket family.
   std::string GetSocketFamilyName() const {
     return Nl80211Socket::kSocketFamilyName;
   }
 
-  virtual uint32 Send(KernelBoundNlMessage *message);
-
  private:
   // The family name of this particular netlink socket.
   static const char kSocketFamilyName[];
 
   // The id returned by a call to 'genl_ctrl_resolve'.
-  int nl80211_id_;
+  int family_id_;
 
   DISALLOW_COPY_AND_ASSIGN(Nl80211Socket);
 };