shill: Separates Attributes into Netlink and Nl80211 classes.

This CL separates Nl80211Attribute into a base class (NetlinkAttribute)
and an nl80211-specific portion, replaces the enum 'nl80211_attrs' with
'int' in various places (to genericize those operations), and makes
|CreateAndInitFromNlAttr| take an attribute-type-specific factory as a
parameter.  This work prepares the Config80211 code to handle control
messages along with control message-specific attributes in preparation
for Config80211 to make the transition from using libnl for kernel
communication to using netlink sockets directly.

BUG=chromium-os:39022
TEST=unittest.

Change-Id: Icbd9d171b16eb0088c90be9de1092006b75e1e42
Reviewed-on: https://gerrit.chromium.org/gerrit/44108
Reviewed-by: Paul Stewart <pstew@chromium.org>
Reviewed-by: Christopher Wiley <wiley@chromium.org>
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Commit-Queue: Wade Guthrie <wdg@chromium.org>
Tested-by: Wade Guthrie <wdg@chromium.org>
diff --git a/attribute_list.cc b/attribute_list.cc
index 2717a00..03f22b3 100644
--- a/attribute_list.cc
+++ b/attribute_list.cc
@@ -27,18 +27,19 @@
 
 namespace shill {
 
-bool AttributeList::CreateAttribute(nl80211_attrs id) {
+bool AttributeList::CreateAttribute(
+    int id, AttributeList::NewFromIdMethod factory) {
   if (ContainsKey(attributes_, id)) {
     LOG(ERROR) << "Trying to re-add attribute: " << id;
     return false;
   }
-  attributes_[id] = AttributePointer(Nl80211Attribute::NewFromName(id));
+  attributes_[id] = AttributePointer(factory.Run(id));
   return true;
 }
 
-bool AttributeList::CreateAndInitFromNlAttr(nl80211_attrs id,
-                                            const nlattr *data) {
-  if (!CreateAttribute(id)) {
+bool AttributeList::CreateAndInitAttribute(
+    int id, const nlattr *data, AttributeList::NewFromIdMethod factory) {
+  if (!CreateAttribute(id, factory)) {
     return false;
   }
   return attributes_[id]->InitFromNlAttr(data);
@@ -65,7 +66,7 @@
 // U8 Attribute.
 
 bool AttributeList::GetU8AttributeValue(int id, uint8_t *value) const {
-  Nl80211Attribute *attribute = GetAttribute(id);
+  NetlinkAttribute *attribute = GetAttribute(id);
   if (!attribute)
     return false;
   return attribute->GetU8Value(value);
@@ -77,12 +78,12 @@
     return false;
   }
   attributes_[id] = AttributePointer(
-      new Nl80211U8Attribute(id, id_string));
+      new NetlinkU8Attribute(id, id_string));
   return true;
 }
 
 bool AttributeList::SetU8AttributeValue(int id, uint8_t value) const {
-  Nl80211Attribute *attribute = GetAttribute(id);
+  NetlinkAttribute *attribute = GetAttribute(id);
   if (!attribute)
     return false;
   return attribute->SetU8Value(value);
@@ -92,7 +93,7 @@
 // U16 Attribute.
 
 bool AttributeList::GetU16AttributeValue(int id, uint16_t *value) const {
-  Nl80211Attribute *attribute = GetAttribute(id);
+  NetlinkAttribute *attribute = GetAttribute(id);
   if (!attribute)
     return false;
   return attribute->GetU16Value(value);
@@ -104,12 +105,12 @@
     return false;
   }
   attributes_[id] = AttributePointer(
-      new Nl80211U16Attribute(id, id_string));
+      new NetlinkU16Attribute(id, id_string));
   return true;
 }
 
 bool AttributeList::SetU16AttributeValue(int id, uint16_t value) const {
-  Nl80211Attribute *attribute = GetAttribute(id);
+  NetlinkAttribute *attribute = GetAttribute(id);
   if (!attribute)
     return false;
   return attribute->SetU16Value(value);
@@ -118,7 +119,7 @@
 // U32 Attribute.
 
 bool AttributeList::GetU32AttributeValue(int id, uint32_t *value) const {
-  Nl80211Attribute *attribute = GetAttribute(id);
+  NetlinkAttribute *attribute = GetAttribute(id);
   if (!attribute)
     return false;
   return attribute->GetU32Value(value);
@@ -130,12 +131,12 @@
     return false;
   }
   attributes_[id] = AttributePointer(
-      new Nl80211U32Attribute(id, id_string));
+      new NetlinkU32Attribute(id, id_string));
   return true;
 }
 
 bool AttributeList::SetU32AttributeValue(int id, uint32_t value) const {
-  Nl80211Attribute *attribute = GetAttribute(id);
+  NetlinkAttribute *attribute = GetAttribute(id);
   if (!attribute)
     return false;
   return attribute->SetU32Value(value);
@@ -144,7 +145,7 @@
 // U64 Attribute.
 
 bool AttributeList::GetU64AttributeValue(int id, uint64_t *value) const {
-  Nl80211Attribute *attribute = GetAttribute(id);
+  NetlinkAttribute *attribute = GetAttribute(id);
   if (!attribute)
     return false;
   return attribute->GetU64Value(value);
@@ -156,12 +157,12 @@
     return false;
   }
   attributes_[id] = AttributePointer(
-      new Nl80211U64Attribute(id, id_string));
+      new NetlinkU64Attribute(id, id_string));
   return true;
 }
 
 bool AttributeList::SetU64AttributeValue(int id, uint64_t value) const {
-  Nl80211Attribute *attribute = GetAttribute(id);
+  NetlinkAttribute *attribute = GetAttribute(id);
   if (!attribute)
     return false;
   return attribute->SetU64Value(value);
@@ -170,7 +171,7 @@
 // Flag Attribute.
 
 bool AttributeList::GetFlagAttributeValue(int id, bool *value) const {
-  Nl80211Attribute *attribute = GetAttribute(id);
+  NetlinkAttribute *attribute = GetAttribute(id);
   if (!attribute)
     return false;
   return attribute->GetFlagValue(value);
@@ -182,12 +183,12 @@
     return false;
   }
   attributes_[id] = AttributePointer(
-      new Nl80211FlagAttribute(id, id_string));
+      new NetlinkFlagAttribute(id, id_string));
   return true;
 }
 
 bool AttributeList::SetFlagAttributeValue(int id, bool value) const {
-  Nl80211Attribute *attribute = GetAttribute(id);
+  NetlinkAttribute *attribute = GetAttribute(id);
   if (!attribute)
     return false;
   return attribute->SetFlagValue(value);
@@ -204,7 +205,7 @@
 // String Attribute.
 
 bool AttributeList::GetStringAttributeValue(int id, string *value) const {
-  Nl80211Attribute *attribute = GetAttribute(id);
+  NetlinkAttribute *attribute = GetAttribute(id);
   if (!attribute)
     return false;
   return attribute->GetStringValue(value);
@@ -216,12 +217,12 @@
     return false;
   }
   attributes_[id] = AttributePointer(
-      new Nl80211StringAttribute(id, id_string));
+      new NetlinkStringAttribute(id, id_string));
   return true;
 }
 
 bool AttributeList::SetStringAttributeValue(int id, string value) const {
-  Nl80211Attribute *attribute = GetAttribute(id);
+  NetlinkAttribute *attribute = GetAttribute(id);
   if (!attribute)
     return false;
   return attribute->SetStringValue(value);
@@ -231,7 +232,7 @@
 
 bool AttributeList::GetNestedAttributeValue(
     int id, WeakPtr<AttributeList> *value) const {
-  Nl80211Attribute *attribute = GetAttribute(id);
+  NetlinkAttribute *attribute = GetAttribute(id);
   if (!attribute)
     return false;
   return attribute->GetNestedValue(value);
@@ -243,7 +244,7 @@
     return false;
   }
   attributes_[id] = AttributePointer(
-      new Nl80211NestedAttribute(id, id_string));
+      new NetlinkNestedAttribute(id, id_string));
   return true;
 }
 
@@ -251,7 +252,7 @@
 
 bool AttributeList::GetRawAttributeValue(int id,
                                          ByteString *output) const {
-  Nl80211Attribute *attribute = GetAttribute(id);
+  NetlinkAttribute *attribute = GetAttribute(id);
   if (!attribute)
     return false;
 
@@ -273,18 +274,18 @@
   return true;
 }
 
-const Nl80211RawAttribute *AttributeList::GetRawAttribute(
+const NetlinkRawAttribute *AttributeList::GetRawAttribute(
     int id) const {
   if (!HasRawAttribute(id)) {
     LOG(ERROR) << "No attribute " << id << " of type kTypeRaw exists.";
     return NULL;
   }
-  const Nl80211RawAttribute *attr =
-      reinterpret_cast<const Nl80211RawAttribute *>(GetAttribute(id));
+  const NetlinkRawAttribute *attr =
+      reinterpret_cast<const NetlinkRawAttribute *>(GetAttribute(id));
   return attr;
 }
 
-Nl80211Attribute *AttributeList::GetAttribute(int id) const {
+NetlinkAttribute *AttributeList::GetAttribute(int id) const {
   map<int, AttributePointer>::const_iterator i;
   i = attributes_.find(id);
   if (i == attributes_.end()) {
@@ -300,7 +301,7 @@
     LOG(ERROR) << "FALSE - Didn't find id " << id;
     return false;
   }
-  return (i->second->datatype() == Nl80211Attribute::kTypeRaw) ? true : false;
+  return (i->second->datatype() == NetlinkAttribute::kTypeRaw) ? true : false;
 }
 
 
diff --git a/attribute_list.h b/attribute_list.h
index 7a3d19b..8c1b5d3 100644
--- a/attribute_list.h
+++ b/attribute_list.h
@@ -12,28 +12,31 @@
 #include <string>
 #include <tr1/memory>
 
+#include <base/bind.h>
 #include <base/memory/weak_ptr.h>
 
 struct nlattr;
 namespace shill {
 
 class ByteString;
-class Nl80211Attribute;
-class Nl80211RawAttribute;
+class NetlinkAttribute;
+class NetlinkRawAttribute;
 
 class AttributeList : public base::SupportsWeakPtr<AttributeList> {
  public:
-  typedef std::tr1::shared_ptr<Nl80211Attribute> AttributePointer;
+  typedef std::tr1::shared_ptr<NetlinkAttribute> AttributePointer;
+  typedef base::Callback<NetlinkAttribute *(int id)> NewFromIdMethod;
 
-  // Instantiates an Nl80211Attribute of the appropriate type from |id|,
+  // Instantiates an NetlinkAttribute of the appropriate type from |id|,
   // and adds it to |attributes_|.
-  bool CreateAttribute(nl80211_attrs id);
+  bool CreateAttribute(int id, NewFromIdMethod factory);
 
-  // Instantiates an Nl80211Attribute of the appropriate type from |id|,
+  // Instantiates an NetlinkAttribute of the appropriate type from |id|,
   // initializes it from |data|, and adds it to |attributes_|.
   // TODO(wdg): This is a stop-gap for use before message constructors add
   // their attributes as message templates.
-  bool CreateAndInitFromNlAttr(nl80211_attrs id, const nlattr *data);
+  bool CreateAndInitAttribute(int id, const nlattr *data,
+                              AttributeList::NewFromIdMethod factory);
 
   // Prints the attribute list with each attribute using no less than 1 line.
   // |indent| indicates the amout of leading spaces to be printed (useful for
@@ -65,12 +68,12 @@
   // TODO(wdg): |GetRawAttribute| is a stopgap to support various
   // Nl80211Message::ToString methods and must, once those are re-written,
   // be destroyed.
-  const Nl80211RawAttribute *GetRawAttribute(int id) const;
+  const NetlinkRawAttribute *GetRawAttribute(int id) const;
 
  private:
   // The Create*Attribute and Set*Attribute methods are specifically for use
   // by nested attributes to add their sub-attributes.  Classes derived from
-  // Nl80211NestedAttribute should be added, here.
+  // NetlinkNestedAttribute should be added, here.
   friend class Nl80211AttributeCqm;
   friend class Nl80211AttributeStaInfo;
 
@@ -96,7 +99,7 @@
   // No |SetNestedAttributeValue| method as it would make no sense.
 
   // Using this to get around issues with const and operator[].
-  Nl80211Attribute *GetAttribute(int id) const;
+  NetlinkAttribute *GetAttribute(int id) const;
 
   // TODO(wdg): This is only used to support |GetRawAttribute|.  Delete this
   // when that goes away.
diff --git a/nl80211_attribute.cc b/nl80211_attribute.cc
index a8a9218..1dc5c4d 100644
--- a/nl80211_attribute.cc
+++ b/nl80211_attribute.cc
@@ -28,7 +28,7 @@
 
 namespace shill {
 
-Nl80211Attribute::Nl80211Attribute(int id,
+NetlinkAttribute::NetlinkAttribute(int id,
                                    const char *id_string,
                                    Type datatype,
                                    const char *datatype_string)
@@ -36,8 +36,8 @@
       datatype_string_(datatype_string) {}
 
 // static
-Nl80211Attribute *Nl80211Attribute::NewFromName(nl80211_attrs id) {
-  scoped_ptr<Nl80211Attribute> attr;
+NetlinkAttribute *NetlinkAttribute::NewNl80211AttributeFromId(int id) {
+  scoped_ptr<NetlinkAttribute> attr;
   switch (id) {
     case NL80211_ATTR_COOKIE:
       attr.reset(new Nl80211AttributeCookie());
@@ -115,14 +115,14 @@
       attr.reset(new Nl80211AttributeWiphyName());
       break;
     default:
-      attr.reset(new Nl80211AttributeGeneric(id));
+      attr.reset(new NetlinkAttributeGeneric(id));
       break;
   }
   return attr.release();
 }
 
 // Duplicate attribute data, store in map indexed on |id|.
-bool Nl80211Attribute::InitFromNlAttr(const nlattr *other) {
+bool NetlinkAttribute::InitFromNlAttr(const nlattr *other) {
   if (!other) {
     LOG(ERROR) << "NULL data";
     return false;
@@ -133,84 +133,84 @@
   return true;
 }
 
-bool Nl80211Attribute::GetU8Value(uint8_t *value) const {
+bool NetlinkAttribute::GetU8Value(uint8_t *value) const {
   LOG(ERROR) << "Attribute is not of type 'U8'";
   return false;
 }
 
-bool Nl80211Attribute::SetU8Value(uint8_t value) {
+bool NetlinkAttribute::SetU8Value(uint8_t value) {
   LOG(ERROR) << "Attribute is not of type 'U8'";
   return false;
 }
 
-bool Nl80211Attribute::GetU16Value(uint16_t *value) const {
+bool NetlinkAttribute::GetU16Value(uint16_t *value) const {
   LOG(ERROR) << "Attribute is not of type 'U16'";
   return false;
 }
 
-bool Nl80211Attribute::SetU16Value(uint16_t value) {
+bool NetlinkAttribute::SetU16Value(uint16_t value) {
   LOG(ERROR) << "Attribute is not of type 'U16'";
   return false;
 }
 
-bool Nl80211Attribute::GetU32Value(uint32_t *value) const {
+bool NetlinkAttribute::GetU32Value(uint32_t *value) const {
   LOG(ERROR) << "Attribute is not of type 'U32'";
   return false;
 }
 
-bool Nl80211Attribute::SetU32Value(uint32_t value) {
+bool NetlinkAttribute::SetU32Value(uint32_t value) {
   LOG(ERROR) << "Attribute is not of type 'U32'";
   return false;
 }
 
-bool Nl80211Attribute::GetU64Value(uint64_t *value) const {
+bool NetlinkAttribute::GetU64Value(uint64_t *value) const {
   LOG(ERROR) << "Attribute is not of type 'U64'";
   return false;
 }
 
-bool Nl80211Attribute::SetU64Value(uint64_t value) {
+bool NetlinkAttribute::SetU64Value(uint64_t value) {
   LOG(ERROR) << "Attribute is not of type 'U64'";
   return false;
 }
 
-bool Nl80211Attribute::GetFlagValue(bool *value) const {
+bool NetlinkAttribute::GetFlagValue(bool *value) const {
   LOG(ERROR) << "Attribute is not of type 'Flag'";
   return false;
 }
 
-bool Nl80211Attribute::SetFlagValue(bool value) {
+bool NetlinkAttribute::SetFlagValue(bool value) {
   LOG(ERROR) << "Attribute is not of type 'Flag'";
   return false;
 }
 
-bool Nl80211Attribute::GetStringValue(string *value) const {
+bool NetlinkAttribute::GetStringValue(string *value) const {
   LOG(ERROR) << "Attribute is not of type 'String'";
   return false;
 }
 
-bool Nl80211Attribute::SetStringValue(string value) {
+bool NetlinkAttribute::SetStringValue(string value) {
   LOG(ERROR) << "Attribute is not of type 'String'";
   return false;
 }
 
-bool Nl80211Attribute::GetNestedValue(WeakPtr<AttributeList> *value) {
+bool NetlinkAttribute::GetNestedValue(WeakPtr<AttributeList> *value) {
   LOG(ERROR) << "Attribute is not of type 'Nested'";
   return false;
 }
 
-bool Nl80211Attribute::GetRawValue(ByteString *value) const {
+bool NetlinkAttribute::GetRawValue(ByteString *value) const {
   LOG(ERROR) << "Attribute is not of type 'Raw'";
   return false;
 }
 
-void Nl80211Attribute::Print(int log_level, int indent) const {
+void NetlinkAttribute::Print(int log_level, int indent) const {
   string attribute_value;
   SLOG(WiFi, log_level) << HeaderToPrint(indent) << " "
                         << (ToString(&attribute_value) ? attribute_value :
                             "<DOES NOT EXIST>");
 }
 
-string Nl80211Attribute::RawToString() const {
+string NetlinkAttribute::RawToString() const {
   string output = " === RAW: ";
 
   if (!has_a_value_) {
@@ -232,7 +232,7 @@
   return output;
 }
 
-string Nl80211Attribute::HeaderToPrint(int indent) const {
+string NetlinkAttribute::HeaderToPrint(int indent) const {
   static const int kSpacesPerIndent = 2;
   return StringPrintf("%*s%s(%d) %s %s=",
             indent * kSpacesPerIndent, "",
@@ -242,7 +242,7 @@
             ((has_a_value()) ?  "": "UNINITIALIZED "));
 }
 
-ByteString Nl80211Attribute::EncodeGeneric(const unsigned char *data,
+ByteString NetlinkAttribute::EncodeGeneric(const unsigned char *data,
                                            int bytes) const {
   nlattr header;
   header.nla_type = id();
@@ -256,13 +256,13 @@
   return result;
 }
 
-// Nl80211U8Attribute
+// NetlinkU8Attribute
 
-const char Nl80211U8Attribute::kMyTypeString[] = "uint8_t";
-const Nl80211Attribute::Type Nl80211U8Attribute::kType =
-    Nl80211Attribute::kTypeU8;
+const char NetlinkU8Attribute::kMyTypeString[] = "uint8_t";
+const NetlinkAttribute::Type NetlinkU8Attribute::kType =
+    NetlinkAttribute::kTypeU8;
 
-bool Nl80211U8Attribute::InitFromNlAttr(const nlattr *input) {
+bool NetlinkU8Attribute::InitFromNlAttr(const nlattr *input) {
   if (!input) {
     LOG(ERROR) << "Null |input| parameter";
     return false;
@@ -270,10 +270,10 @@
 
   uint8_t data = NlaGetU8(input);
   SetU8Value(data);
-  return Nl80211Attribute::InitFromNlAttr(input);
+  return NetlinkAttribute::InitFromNlAttr(input);
 }
 
-bool Nl80211U8Attribute::GetU8Value(uint8_t *output) const {
+bool NetlinkU8Attribute::GetU8Value(uint8_t *output) const {
   if (!has_a_value_) {
     SLOG(WiFi, 7) << "U8 attribute " << id_string()
                   << " hasn't been set to any value.";
@@ -285,13 +285,13 @@
   return true;
 }
 
-bool Nl80211U8Attribute::SetU8Value(uint8_t new_value) {
+bool NetlinkU8Attribute::SetU8Value(uint8_t new_value) {
   value_ = new_value;
   has_a_value_ = true;
   return true;
 }
 
-bool Nl80211U8Attribute::ToString(string *output) const {
+bool NetlinkU8Attribute::ToString(string *output) const {
   if (!output) {
     LOG(ERROR) << "Null |output| parameter";
     return false;
@@ -303,19 +303,19 @@
   return true;
 }
 
-ByteString Nl80211U8Attribute::Encode() const {
-  return Nl80211Attribute::EncodeGeneric(
+ByteString NetlinkU8Attribute::Encode() const {
+  return NetlinkAttribute::EncodeGeneric(
       reinterpret_cast<const unsigned char *>(&value_), sizeof(value_));
 }
 
 
-// Nl80211U16Attribute
+// NetlinkU16Attribute
 
-const char Nl80211U16Attribute::kMyTypeString[] = "uint16_t";
-const Nl80211Attribute::Type Nl80211U16Attribute::kType =
-    Nl80211Attribute::kTypeU16;
+const char NetlinkU16Attribute::kMyTypeString[] = "uint16_t";
+const NetlinkAttribute::Type NetlinkU16Attribute::kType =
+    NetlinkAttribute::kTypeU16;
 
-bool Nl80211U16Attribute::InitFromNlAttr(const nlattr *input) {
+bool NetlinkU16Attribute::InitFromNlAttr(const nlattr *input) {
   if (!input) {
     LOG(ERROR) << "Null |input| parameter";
     return false;
@@ -323,10 +323,10 @@
 
   uint16_t data = NlaGetU16(input);
   SetU16Value(data);
-  return Nl80211Attribute::InitFromNlAttr(input);
+  return NetlinkAttribute::InitFromNlAttr(input);
 }
 
-bool Nl80211U16Attribute::GetU16Value(uint16_t *output) const {
+bool NetlinkU16Attribute::GetU16Value(uint16_t *output) const {
   if (!has_a_value_) {
     SLOG(WiFi, 7)  << "U16 attribute " << id_string()
                    << " hasn't been set to any value.";
@@ -338,13 +338,13 @@
   return true;
 }
 
-bool Nl80211U16Attribute::SetU16Value(uint16_t new_value) {
+bool NetlinkU16Attribute::SetU16Value(uint16_t new_value) {
   value_ = new_value;
   has_a_value_ = true;
   return true;
 }
 
-bool Nl80211U16Attribute::ToString(string *output) const {
+bool NetlinkU16Attribute::ToString(string *output) const {
   if (!output) {
     LOG(ERROR) << "Null |output| parameter";
     return false;
@@ -356,18 +356,18 @@
   return true;
 }
 
-ByteString Nl80211U16Attribute::Encode() const {
-  return Nl80211Attribute::EncodeGeneric(
+ByteString NetlinkU16Attribute::Encode() const {
+  return NetlinkAttribute::EncodeGeneric(
       reinterpret_cast<const unsigned char *>(&value_), sizeof(value_));
 }
 
-// Nl80211U32Attribute::
+// NetlinkU32Attribute::
 
-const char Nl80211U32Attribute::kMyTypeString[] = "uint32_t";
-const Nl80211Attribute::Type Nl80211U32Attribute::kType =
-    Nl80211Attribute::kTypeU32;
+const char NetlinkU32Attribute::kMyTypeString[] = "uint32_t";
+const NetlinkAttribute::Type NetlinkU32Attribute::kType =
+    NetlinkAttribute::kTypeU32;
 
-bool Nl80211U32Attribute::InitFromNlAttr(const nlattr *input) {
+bool NetlinkU32Attribute::InitFromNlAttr(const nlattr *input) {
   if (!input) {
     LOG(ERROR) << "Null |input| parameter";
     return false;
@@ -375,10 +375,10 @@
 
   uint32_t data = NlaGetU32(input);
   SetU32Value(data);
-  return Nl80211Attribute::InitFromNlAttr(input);
+  return NetlinkAttribute::InitFromNlAttr(input);
 }
 
-bool Nl80211U32Attribute::GetU32Value(uint32_t *output) const {
+bool NetlinkU32Attribute::GetU32Value(uint32_t *output) const {
   if (!has_a_value_) {
     SLOG(WiFi, 7)  << "U32 attribute " << id_string()
                    << " hasn't been set to any value.";
@@ -390,13 +390,13 @@
   return true;
 }
 
-bool Nl80211U32Attribute::SetU32Value(uint32_t new_value) {
+bool NetlinkU32Attribute::SetU32Value(uint32_t new_value) {
   value_ = new_value;
   has_a_value_ = true;
   return true;
 }
 
-bool Nl80211U32Attribute::ToString(string *output) const {
+bool NetlinkU32Attribute::ToString(string *output) const {
   if (!output) {
     LOG(ERROR) << "Null |output| parameter";
     return false;
@@ -408,18 +408,18 @@
   return true;
 }
 
-ByteString Nl80211U32Attribute::Encode() const {
-  return Nl80211Attribute::EncodeGeneric(
+ByteString NetlinkU32Attribute::Encode() const {
+  return NetlinkAttribute::EncodeGeneric(
       reinterpret_cast<const unsigned char *>(&value_), sizeof(value_));
 }
 
-// Nl80211U64Attribute
+// NetlinkU64Attribute
 
-const char Nl80211U64Attribute::kMyTypeString[] = "uint64_t";
-const Nl80211Attribute::Type Nl80211U64Attribute::kType =
-    Nl80211Attribute::kTypeU64;
+const char NetlinkU64Attribute::kMyTypeString[] = "uint64_t";
+const NetlinkAttribute::Type NetlinkU64Attribute::kType =
+    NetlinkAttribute::kTypeU64;
 
-bool Nl80211U64Attribute::InitFromNlAttr(const nlattr *input) {
+bool NetlinkU64Attribute::InitFromNlAttr(const nlattr *input) {
   if (!input) {
     LOG(ERROR) << "Null |input| parameter";
     return false;
@@ -427,10 +427,10 @@
 
   uint64_t data = NlaGetU64(input);
   SetU64Value(data);
-  return Nl80211Attribute::InitFromNlAttr(input);
+  return NetlinkAttribute::InitFromNlAttr(input);
 }
 
-bool Nl80211U64Attribute::GetU64Value(uint64_t *output) const {
+bool NetlinkU64Attribute::GetU64Value(uint64_t *output) const {
   if (!has_a_value_) {
     SLOG(WiFi, 7)  << "U64 attribute " << id_string()
                    << " hasn't been set to any value.";
@@ -442,13 +442,13 @@
   return true;
 }
 
-bool Nl80211U64Attribute::SetU64Value(uint64_t new_value) {
+bool NetlinkU64Attribute::SetU64Value(uint64_t new_value) {
   value_ = new_value;
   has_a_value_ = true;
   return true;
 }
 
-bool Nl80211U64Attribute::ToString(string *output) const {
+bool NetlinkU64Attribute::ToString(string *output) const {
   if (!output) {
     LOG(ERROR) << "Null |output| parameter";
     return false;
@@ -460,18 +460,18 @@
   return true;
 }
 
-ByteString Nl80211U64Attribute::Encode() const {
-  return Nl80211Attribute::EncodeGeneric(
+ByteString NetlinkU64Attribute::Encode() const {
+  return NetlinkAttribute::EncodeGeneric(
       reinterpret_cast<const unsigned char *>(&value_), sizeof(value_));
 }
 
-// Nl80211FlagAttribute
+// NetlinkFlagAttribute
 
-const char Nl80211FlagAttribute::kMyTypeString[] = "flag";
-const Nl80211Attribute::Type Nl80211FlagAttribute::kType =
-    Nl80211Attribute::kTypeFlag;
+const char NetlinkFlagAttribute::kMyTypeString[] = "flag";
+const NetlinkAttribute::Type NetlinkFlagAttribute::kType =
+    NetlinkAttribute::kTypeFlag;
 
-bool Nl80211FlagAttribute::InitFromNlAttr(const nlattr *input) {
+bool NetlinkFlagAttribute::InitFromNlAttr(const nlattr *input) {
   if (!input) {
     LOG(ERROR) << "Null |input| parameter";
     return false;
@@ -479,11 +479,11 @@
 
   // The existence of the parameter means it's true
   SetFlagValue(true);
-  return Nl80211Attribute::InitFromNlAttr(input);
+  return NetlinkAttribute::InitFromNlAttr(input);
 }
 
 
-bool Nl80211FlagAttribute::GetFlagValue(bool *output) const {
+bool NetlinkFlagAttribute::GetFlagValue(bool *output) const {
   if (output) {
     // The lack of the existence of the attribute implies 'false'.
     *output = (has_a_value_) ? value_ : false;
@@ -491,13 +491,13 @@
   return true;
 }
 
-bool Nl80211FlagAttribute::SetFlagValue(bool new_value) {
+bool NetlinkFlagAttribute::SetFlagValue(bool new_value) {
   value_ = new_value;
   has_a_value_ = true;
   return true;
 }
 
-bool Nl80211FlagAttribute::ToString(string *output) const {
+bool NetlinkFlagAttribute::ToString(string *output) const {
   if (!output) {
     LOG(ERROR) << "Null |output| parameter";
     return false;
@@ -509,30 +509,30 @@
   return true;
 }
 
-ByteString Nl80211FlagAttribute::Encode() const {
+ByteString NetlinkFlagAttribute::Encode() const {
   if (has_a_value_ && value_) {
-    return Nl80211Attribute::EncodeGeneric(NULL, 0);
+    return NetlinkAttribute::EncodeGeneric(NULL, 0);
   }
   return ByteString();  // Encoding of nothing implies 'false'.
 }
 
-// Nl80211StringAttribute
+// NetlinkStringAttribute
 
-const char Nl80211StringAttribute::kMyTypeString[] = "string";
-const Nl80211Attribute::Type Nl80211StringAttribute::kType =
-    Nl80211Attribute::kTypeString;
+const char NetlinkStringAttribute::kMyTypeString[] = "string";
+const NetlinkAttribute::Type NetlinkStringAttribute::kType =
+    NetlinkAttribute::kTypeString;
 
-bool Nl80211StringAttribute::InitFromNlAttr(const nlattr *input) {
+bool NetlinkStringAttribute::InitFromNlAttr(const nlattr *input) {
   if (!input) {
     LOG(ERROR) << "Null |input| parameter";
     return false;
   }
 
   SetStringValue(NlaGetString(input));
-  return Nl80211Attribute::InitFromNlAttr(input);
+  return NetlinkAttribute::InitFromNlAttr(input);
 }
 
-bool Nl80211StringAttribute::GetStringValue(string *output) const {
+bool NetlinkStringAttribute::GetStringValue(string *output) const {
   if (!has_a_value_) {
     SLOG(WiFi, 7)  << "String attribute " << id_string()
                    << " hasn't been set to any value.";
@@ -544,13 +544,13 @@
   return true;
 }
 
-bool Nl80211StringAttribute::SetStringValue(const string new_value) {
+bool NetlinkStringAttribute::SetStringValue(const string new_value) {
   value_ = new_value;
   has_a_value_ = true;
   return true;
 }
 
-bool Nl80211StringAttribute::ToString(string *output) const {
+bool NetlinkStringAttribute::ToString(string *output) const {
   if (!output) {
     LOG(ERROR) << "Null |output| parameter";
     return false;
@@ -563,21 +563,21 @@
   return true;
 }
 
-ByteString Nl80211StringAttribute::Encode() const {
-  return Nl80211Attribute::EncodeGeneric(
+ByteString NetlinkStringAttribute::Encode() const {
+  return NetlinkAttribute::EncodeGeneric(
       reinterpret_cast<const unsigned char *>(value_.c_str()), value_.size());
 }
 
-// Nl80211NestedAttribute
-const char Nl80211NestedAttribute::kMyTypeString[] = "nested";
-const Nl80211Attribute::Type Nl80211NestedAttribute::kType =
-    Nl80211Attribute::kTypeNested;
+// NetlinkNestedAttribute
+const char NetlinkNestedAttribute::kMyTypeString[] = "nested";
+const NetlinkAttribute::Type NetlinkNestedAttribute::kType =
+    NetlinkAttribute::kTypeNested;
 
-Nl80211NestedAttribute::Nl80211NestedAttribute(int id,
+NetlinkNestedAttribute::NetlinkNestedAttribute(int id,
                                                const char *id_string) :
-    Nl80211Attribute(id, id_string, kType, kMyTypeString) {}
+    NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
 
-bool Nl80211NestedAttribute::GetNestedValue(WeakPtr<AttributeList> *output) {
+bool NetlinkNestedAttribute::GetNestedValue(WeakPtr<AttributeList> *output) {
   if (!has_a_value_) {
     SLOG(WiFi, 7)  << "Nested attribute " << id_string()
                    << " hasn't been set to any value.";
@@ -589,26 +589,26 @@
   return true;
 }
 
-// Nl80211RawAttribute
+// NetlinkRawAttribute
 
-const char Nl80211RawAttribute::kMyTypeString[] = "<raw>";
-const Nl80211Attribute::Type Nl80211RawAttribute::kType =
-    Nl80211Attribute::kTypeRaw;
+const char NetlinkRawAttribute::kMyTypeString[] = "<raw>";
+const NetlinkAttribute::Type NetlinkRawAttribute::kType =
+    NetlinkAttribute::kTypeRaw;
 
-bool Nl80211RawAttribute::InitFromNlAttr(const nlattr *input) {
+bool NetlinkRawAttribute::InitFromNlAttr(const nlattr *input) {
   if (!input) {
     LOG(ERROR) << "Null |input| parameter";
     return false;
   }
 
-  if (!Nl80211Attribute::InitFromNlAttr(input)) {
+  if (!NetlinkAttribute::InitFromNlAttr(input)) {
     return false;
   }
   has_a_value_ = true;
   return true;
 }
 
-bool Nl80211RawAttribute::GetRawValue(ByteString *output) const {
+bool NetlinkRawAttribute::GetRawValue(ByteString *output) const {
   if (!has_a_value_) {
     SLOG(WiFi, 7)  << "Raw attribute " << id_string()
                    << " hasn't been set to any value.";
@@ -620,7 +620,7 @@
   return true;
 }
 
-bool Nl80211RawAttribute::ToString(string *output) const {
+bool NetlinkRawAttribute::ToString(string *output) const {
   if (!output) {
     LOG(ERROR) << "Null |output| parameter";
     return false;
@@ -642,14 +642,14 @@
 // Specific Attributes.
 
 
-const nl80211_attrs Nl80211AttributeCookie::kName = NL80211_ATTR_COOKIE;
+const int Nl80211AttributeCookie::kName = NL80211_ATTR_COOKIE;
 const char Nl80211AttributeCookie::kNameString[] = "NL80211_ATTR_COOKIE";
 
-const nl80211_attrs Nl80211AttributeCqm::kName = NL80211_ATTR_CQM;
+const int Nl80211AttributeCqm::kName = NL80211_ATTR_CQM;
 const char Nl80211AttributeCqm::kNameString[] = "NL80211_ATTR_CQM";
 
 Nl80211AttributeCqm::Nl80211AttributeCqm()
-      : Nl80211NestedAttribute(kName, kNameString) {
+      : NetlinkNestedAttribute(kName, kNameString) {
   value_.CreateU32Attribute(NL80211_ATTR_CQM_RSSI_THOLD,
                             "NL80211_ATTR_CQM_RSSI_THOLD");
   value_.CreateU32Attribute(NL80211_ATTR_CQM_RSSI_HYST,
@@ -706,64 +706,64 @@
   return true;
 }
 
-const nl80211_attrs Nl80211AttributeDisconnectedByAp::kName
+const int Nl80211AttributeDisconnectedByAp::kName
     = NL80211_ATTR_DISCONNECTED_BY_AP;
 const char Nl80211AttributeDisconnectedByAp::kNameString[]
     = "NL80211_ATTR_DISCONNECTED_BY_AP";
 
-const nl80211_attrs Nl80211AttributeDuration::kName = NL80211_ATTR_DURATION;
+const int Nl80211AttributeDuration::kName = NL80211_ATTR_DURATION;
 const char Nl80211AttributeDuration::kNameString[] = "NL80211_ATTR_DURATION";
 
-const nl80211_attrs Nl80211AttributeFrame::kName = NL80211_ATTR_FRAME;
+const int Nl80211AttributeFrame::kName = NL80211_ATTR_FRAME;
 const char Nl80211AttributeFrame::kNameString[] = "NL80211_ATTR_FRAME";
 
-const nl80211_attrs Nl80211AttributeGeneration::kName = NL80211_ATTR_GENERATION;
+const int Nl80211AttributeGeneration::kName = NL80211_ATTR_GENERATION;
 const char Nl80211AttributeGeneration::kNameString[]
     = "NL80211_ATTR_GENERATION";
 
-const nl80211_attrs Nl80211AttributeIfindex::kName = NL80211_ATTR_IFINDEX;
+const int Nl80211AttributeIfindex::kName = NL80211_ATTR_IFINDEX;
 const char Nl80211AttributeIfindex::kNameString[] = "NL80211_ATTR_IFINDEX";
 
-const nl80211_attrs Nl80211AttributeKeyIdx::kName = NL80211_ATTR_KEY_IDX;
+const int Nl80211AttributeKeyIdx::kName = NL80211_ATTR_KEY_IDX;
 const char Nl80211AttributeKeyIdx::kNameString[] = "NL80211_ATTR_KEY_IDX";
 
-const nl80211_attrs Nl80211AttributeKeySeq::kName = NL80211_ATTR_KEY_SEQ;
+const int Nl80211AttributeKeySeq::kName = NL80211_ATTR_KEY_SEQ;
 const char Nl80211AttributeKeySeq::kNameString[] = "NL80211_ATTR_KEY_SEQ";
 
-const nl80211_attrs Nl80211AttributeKeyType::kName = NL80211_ATTR_KEY_TYPE;
+const int Nl80211AttributeKeyType::kName = NL80211_ATTR_KEY_TYPE;
 const char Nl80211AttributeKeyType::kNameString[] = "NL80211_ATTR_KEY_TYPE";
 
-const nl80211_attrs Nl80211AttributeMac::kName = NL80211_ATTR_MAC;
+const int Nl80211AttributeMac::kName = NL80211_ATTR_MAC;
 const char Nl80211AttributeMac::kNameString[] = "NL80211_ATTR_MAC";
 
-const nl80211_attrs Nl80211AttributeReasonCode::kName
+const int Nl80211AttributeReasonCode::kName
     = NL80211_ATTR_REASON_CODE;
 const char Nl80211AttributeReasonCode::kNameString[]
     = "NL80211_ATTR_REASON_CODE";
 
-const nl80211_attrs Nl80211AttributeRegAlpha2::kName = NL80211_ATTR_REG_ALPHA2;
+const int Nl80211AttributeRegAlpha2::kName = NL80211_ATTR_REG_ALPHA2;
 const char Nl80211AttributeRegAlpha2::kNameString[] = "NL80211_ATTR_REG_ALPHA2";
 
-const nl80211_attrs Nl80211AttributeRegInitiator::kName
+const int Nl80211AttributeRegInitiator::kName
     = NL80211_ATTR_REG_INITIATOR;
 const char Nl80211AttributeRegInitiator::kNameString[]
     = "NL80211_ATTR_REG_INITIATOR";
 
-const nl80211_attrs Nl80211AttributeRegType::kName = NL80211_ATTR_REG_TYPE;
+const int Nl80211AttributeRegType::kName = NL80211_ATTR_REG_TYPE;
 const char Nl80211AttributeRegType::kNameString[] = "NL80211_ATTR_REG_TYPE";
 
-const nl80211_attrs Nl80211AttributeRespIe::kName = NL80211_ATTR_RESP_IE;
+const int Nl80211AttributeRespIe::kName = NL80211_ATTR_RESP_IE;
 const char Nl80211AttributeRespIe::kNameString[] = "NL80211_ATTR_RESP_IE";
 
-const nl80211_attrs Nl80211AttributeScanFrequencies::kName
+const int Nl80211AttributeScanFrequencies::kName
     = NL80211_ATTR_SCAN_FREQUENCIES;
 const char Nl80211AttributeScanFrequencies::kNameString[]
     = "NL80211_ATTR_SCAN_FREQUENCIES";
 
-const nl80211_attrs Nl80211AttributeScanSsids::kName = NL80211_ATTR_SCAN_SSIDS;
+const int Nl80211AttributeScanSsids::kName = NL80211_ATTR_SCAN_SSIDS;
 const char Nl80211AttributeScanSsids::kNameString[] = "NL80211_ATTR_SCAN_SSIDS";
 
-const nl80211_attrs Nl80211AttributeStaInfo::kName = NL80211_ATTR_STA_INFO;
+const int Nl80211AttributeStaInfo::kName = NL80211_ATTR_STA_INFO;
 const char Nl80211AttributeStaInfo::kNameString[] = "NL80211_ATTR_STA_INFO";
 
 bool Nl80211AttributeStaInfo::InitFromNlAttr(const nlattr *const_data) {
@@ -776,34 +776,34 @@
   return true;
 }
 
-const nl80211_attrs Nl80211AttributeStatusCode::kName
+const int Nl80211AttributeStatusCode::kName
     = NL80211_ATTR_STATUS_CODE;
 const char Nl80211AttributeStatusCode::kNameString[]
     = "NL80211_ATTR_STATUS_CODE";
 
-const nl80211_attrs Nl80211AttributeSupportMeshAuth::kName
+const int Nl80211AttributeSupportMeshAuth::kName
     = NL80211_ATTR_SUPPORT_MESH_AUTH;
 const char Nl80211AttributeSupportMeshAuth::kNameString[]
     = "NL80211_ATTR_SUPPORT_MESH_AUTH";
 
-const nl80211_attrs Nl80211AttributeTimedOut::kName = NL80211_ATTR_TIMED_OUT;
+const int Nl80211AttributeTimedOut::kName = NL80211_ATTR_TIMED_OUT;
 const char Nl80211AttributeTimedOut::kNameString[] = "NL80211_ATTR_TIMED_OUT";
 
-const nl80211_attrs Nl80211AttributeWiphyFreq::kName = NL80211_ATTR_WIPHY_FREQ;
+const int Nl80211AttributeWiphyFreq::kName = NL80211_ATTR_WIPHY_FREQ;
 const char Nl80211AttributeWiphyFreq::kNameString[] = "NL80211_ATTR_WIPHY_FREQ";
 
-const nl80211_attrs Nl80211AttributeWiphy::kName = NL80211_ATTR_WIPHY;
+const int Nl80211AttributeWiphy::kName = NL80211_ATTR_WIPHY;
 const char Nl80211AttributeWiphy::kNameString[] = "NL80211_ATTR_WIPHY";
 
-const nl80211_attrs Nl80211AttributeWiphyName::kName = NL80211_ATTR_WIPHY_NAME;
+const int Nl80211AttributeWiphyName::kName = NL80211_ATTR_WIPHY_NAME;
 const char Nl80211AttributeWiphyName::kNameString[] = "NL80211_ATTR_WIPHY_NAME";
 
-Nl80211AttributeGeneric::Nl80211AttributeGeneric(nl80211_attrs id)
-    : Nl80211RawAttribute(id, "unused-string") {
+NetlinkAttributeGeneric::NetlinkAttributeGeneric(int id)
+    : NetlinkRawAttribute(id, "unused-string") {
   StringAppendF(&id_string_, "<UNKNOWN ATTRIBUTE %d>", id);
 }
 
-const char *Nl80211AttributeGeneric::id_string() const {
+const char *NetlinkAttributeGeneric::id_string() const {
   return id_string_.c_str();
 }
 
diff --git a/nl80211_attribute.h b/nl80211_attribute.h
index c29d72e..1c555a7 100644
--- a/nl80211_attribute.h
+++ b/nl80211_attribute.h
@@ -22,7 +22,7 @@
 
 namespace shill {
 
-// Nl80211Attribute is an abstract base class that describes an attribute in a
+// NetlinkAttribute 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
 // child classes exist for each individual attribute type.
@@ -31,7 +31,7 @@
 // and a value.  In an nlattr (the underlying format for an attribute in a
 // message), the data is stored as a blob without type information; the writer
 // and reader of the attribute must agree on the data type.
-class Nl80211Attribute {
+class NetlinkAttribute {
  public:
   enum Type {
     kTypeU8,
@@ -45,15 +45,15 @@
     kTypeError
   };
 
-  Nl80211Attribute(int id, const char *id_string,
+  NetlinkAttribute(int id, const char *id_string,
                    Type datatype, const char *datatype_string);
-  virtual ~Nl80211Attribute() {}
+  virtual ~NetlinkAttribute() {}
 
   virtual bool InitFromNlAttr(const nlattr *data);
 
-  // Static factory generates the appropriate Nl80211Attribute object from the
+  // Static factory generates the appropriate NetlinkAttribute object from the
   // raw nlattr data.
-  static Nl80211Attribute *NewFromName(nl80211_attrs id);
+  static NetlinkAttribute *NewFromId(int id);
 
   // Accessors for the attribute's id and datatype information.
   int id() const { return id_; }
@@ -63,7 +63,7 @@
 
   // TODO(wdg): Since |data| is used, externally, to support |nla_parse_nested|,
   // make it protected once all functionality has been brought inside the
-  // Nl80211Attribute classes.
+  // NetlinkAttribute classes.
   //
   // |data_| contains an 'nlattr *' but it's been stored as a ByteString.
   // This returns a pointer to the data in the form that is intended.
@@ -129,6 +129,11 @@
     return nla_get_u64(const_cast<nlattr *>(input));
   }
 
+  // Static factories generate the appropriate attribute object from the
+  // raw nlattr data.
+  static NetlinkAttribute *NewControlAttributeFromId(int id);
+  static NetlinkAttribute *NewNl80211AttributeFromId(int id);
+
  protected:
   // Builds a string to precede a printout of this attribute.
   std::string HeaderToPrint(int indent) const;
@@ -139,7 +144,7 @@
   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
+  // TODO(wdg): When 'data()' is removed, move this to the NetlinkRawAttribute
   // class.
   ByteString data_;
 
@@ -147,7 +152,7 @@
   bool has_a_value_;
 
  private:
-  int id_;  // In the non-nested case, this is really type nl80211_attrs.
+  int id_;
   const char *id_string_;
   Type datatype_;
   const char *datatype_string_;
@@ -155,12 +160,12 @@
 
 // U8.
 
-class Nl80211U8Attribute : public Nl80211Attribute {
+class NetlinkU8Attribute : public NetlinkAttribute {
  public:
   static const char kMyTypeString[];
   static const Type kType;
-  Nl80211U8Attribute(int id, const char *id_string)
-      : Nl80211Attribute(id, id_string, kType, kMyTypeString) {}
+  NetlinkU8Attribute(int id, const char *id_string)
+      : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
   bool InitFromNlAttr(const nlattr *data);
   bool GetU8Value(uint8_t *value) const;
   bool SetU8Value(uint8_t new_value);
@@ -171,28 +176,28 @@
   uint8_t value_;
 };
 
-class Nl80211AttributeKeyIdx : public Nl80211U8Attribute {
+class Nl80211AttributeKeyIdx : public NetlinkU8Attribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
-  Nl80211AttributeKeyIdx() : Nl80211U8Attribute(kName, kNameString) {}
+  Nl80211AttributeKeyIdx() : NetlinkU8Attribute(kName, kNameString) {}
 };
 
-class Nl80211AttributeRegType : public Nl80211U8Attribute {
+class Nl80211AttributeRegType : public NetlinkU8Attribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
-  Nl80211AttributeRegType() : Nl80211U8Attribute(kName, kNameString) {}
+  Nl80211AttributeRegType() : NetlinkU8Attribute(kName, kNameString) {}
 };
 
 // U16.
 
-class Nl80211U16Attribute : public Nl80211Attribute {
+class NetlinkU16Attribute : public NetlinkAttribute {
  public:
   static const char kMyTypeString[];
   static const Type kType;
-  Nl80211U16Attribute(int id, const char *id_string)
-      : Nl80211Attribute(id, id_string, kType, kMyTypeString) {}
+  NetlinkU16Attribute(int id, const char *id_string)
+      : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
   bool InitFromNlAttr(const nlattr *data);
   bool GetU16Value(uint16_t *value) const;
   bool SetU16Value(uint16_t new_value);
@@ -203,28 +208,28 @@
   uint16_t value_;
 };
 
-class Nl80211AttributeReasonCode : public Nl80211U16Attribute {
+class Nl80211AttributeReasonCode : public NetlinkU16Attribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
-  Nl80211AttributeReasonCode() : Nl80211U16Attribute(kName, kNameString) {}
+  Nl80211AttributeReasonCode() : NetlinkU16Attribute(kName, kNameString) {}
 };
 
-class Nl80211AttributeStatusCode : public Nl80211U16Attribute {
+class Nl80211AttributeStatusCode : public NetlinkU16Attribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
-  Nl80211AttributeStatusCode() : Nl80211U16Attribute(kName, kNameString) {}
+  Nl80211AttributeStatusCode() : NetlinkU16Attribute(kName, kNameString) {}
 };
 
 // U32.
 
-class Nl80211U32Attribute : public Nl80211Attribute {
+class NetlinkU32Attribute : public NetlinkAttribute {
  public:
   static const char kMyTypeString[];
   static const Type kType;
-  Nl80211U32Attribute(int id, const char *id_string)
-      : Nl80211Attribute(id, id_string, kType, kMyTypeString) {}
+  NetlinkU32Attribute(int id, const char *id_string)
+      : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
   bool InitFromNlAttr(const nlattr *data);
   bool GetU32Value(uint32_t *value) const;
   bool SetU32Value(uint32_t new_value);
@@ -235,63 +240,63 @@
   uint32_t value_;
 };
 
-class Nl80211AttributeDuration : public Nl80211U32Attribute {
+class Nl80211AttributeDuration : public NetlinkU32Attribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
-  Nl80211AttributeDuration() : Nl80211U32Attribute(kName, kNameString) {}
+  Nl80211AttributeDuration() : NetlinkU32Attribute(kName, kNameString) {}
 };
 
-class Nl80211AttributeGeneration : public Nl80211U32Attribute {
+class Nl80211AttributeGeneration : public NetlinkU32Attribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
-  Nl80211AttributeGeneration() : Nl80211U32Attribute(kName, kNameString) {}
+  Nl80211AttributeGeneration() : NetlinkU32Attribute(kName, kNameString) {}
 };
 
-class Nl80211AttributeIfindex : public Nl80211U32Attribute {
+class Nl80211AttributeIfindex : public NetlinkU32Attribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
-  Nl80211AttributeIfindex() : Nl80211U32Attribute(kName, kNameString) {}
+  Nl80211AttributeIfindex() : NetlinkU32Attribute(kName, kNameString) {}
 };
 
-class Nl80211AttributeKeyType : public Nl80211U32Attribute {
+class Nl80211AttributeKeyType : public NetlinkU32Attribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
-  Nl80211AttributeKeyType() : Nl80211U32Attribute(kName, kNameString) {}
+  Nl80211AttributeKeyType() : NetlinkU32Attribute(kName, kNameString) {}
 };
 
-class Nl80211AttributeRegInitiator : public Nl80211U32Attribute {
+class Nl80211AttributeRegInitiator : public NetlinkU32Attribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
-  Nl80211AttributeRegInitiator() : Nl80211U32Attribute(kName, kNameString) {}
+  Nl80211AttributeRegInitiator() : NetlinkU32Attribute(kName, kNameString) {}
 };
 
-class Nl80211AttributeWiphy : public Nl80211U32Attribute {
+class Nl80211AttributeWiphy : public NetlinkU32Attribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
-  Nl80211AttributeWiphy() : Nl80211U32Attribute(kName, kNameString) {}
+  Nl80211AttributeWiphy() : NetlinkU32Attribute(kName, kNameString) {}
 };
 
-class Nl80211AttributeWiphyFreq : public Nl80211U32Attribute {
+class Nl80211AttributeWiphyFreq : public NetlinkU32Attribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
-  Nl80211AttributeWiphyFreq() : Nl80211U32Attribute(kName, kNameString) {}
+  Nl80211AttributeWiphyFreq() : NetlinkU32Attribute(kName, kNameString) {}
 };
 
 // U64.
 
-class Nl80211U64Attribute : public Nl80211Attribute {
+class NetlinkU64Attribute : public NetlinkAttribute {
  public:
   static const char kMyTypeString[];
   static const Type kType;
-  Nl80211U64Attribute(int id, const char *id_string)
-      : Nl80211Attribute(id, id_string, kType, kMyTypeString) {}
+  NetlinkU64Attribute(int id, const char *id_string)
+      : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
   bool InitFromNlAttr(const nlattr *data);
   bool GetU64Value(uint64_t *value) const;
   bool SetU64Value(uint64_t new_value);
@@ -302,21 +307,21 @@
   uint64_t value_;
 };
 
-class Nl80211AttributeCookie : public Nl80211U64Attribute {
+class Nl80211AttributeCookie : public NetlinkU64Attribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
-  Nl80211AttributeCookie() : Nl80211U64Attribute(kName, kNameString) {}
+  Nl80211AttributeCookie() : NetlinkU64Attribute(kName, kNameString) {}
 };
 
 // Flag.
 
-class Nl80211FlagAttribute : public Nl80211Attribute {
+class NetlinkFlagAttribute : public NetlinkAttribute {
  public:
   static const char kMyTypeString[];
   static const Type kType;
-  Nl80211FlagAttribute(int id, const char *id_string)
-      : Nl80211Attribute(id, id_string, kType, kMyTypeString) {}
+  NetlinkFlagAttribute(int id, const char *id_string)
+      : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
   bool InitFromNlAttr(const nlattr *data);
   bool GetFlagValue(bool *value) const;
   bool SetFlagValue(bool new_value);
@@ -327,37 +332,37 @@
   bool value_;
 };
 
-class Nl80211AttributeDisconnectedByAp : public Nl80211FlagAttribute {
+class Nl80211AttributeDisconnectedByAp : public NetlinkFlagAttribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
   Nl80211AttributeDisconnectedByAp() :
-    Nl80211FlagAttribute(kName, kNameString) {}
+    NetlinkFlagAttribute(kName, kNameString) {}
 };
 
-class Nl80211AttributeSupportMeshAuth : public Nl80211FlagAttribute {
+class Nl80211AttributeSupportMeshAuth : public NetlinkFlagAttribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
   Nl80211AttributeSupportMeshAuth() :
-    Nl80211FlagAttribute(kName, kNameString) {}
+    NetlinkFlagAttribute(kName, kNameString) {}
 };
 
-class Nl80211AttributeTimedOut : public Nl80211FlagAttribute {
+class Nl80211AttributeTimedOut : public NetlinkFlagAttribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
-  Nl80211AttributeTimedOut() : Nl80211FlagAttribute(kName, kNameString) {}
+  Nl80211AttributeTimedOut() : NetlinkFlagAttribute(kName, kNameString) {}
 };
 
 // String.
 
-class Nl80211StringAttribute : public Nl80211Attribute {
+class NetlinkStringAttribute : public NetlinkAttribute {
  public:
   static const char kMyTypeString[];
   static const Type kType;
-  Nl80211StringAttribute(int id, const char *id_string)
-      : Nl80211Attribute(id, id_string, kType, kMyTypeString) {}
+  NetlinkStringAttribute(int id, const char *id_string)
+      : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
   bool InitFromNlAttr(const nlattr *data);
   bool GetStringValue(std::string *value) const;
   bool SetStringValue(const std::string new_value);
@@ -368,27 +373,27 @@
   std::string value_;
 };
 
-class Nl80211AttributeRegAlpha2 : public Nl80211StringAttribute {
+class Nl80211AttributeRegAlpha2 : public NetlinkStringAttribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
-  Nl80211AttributeRegAlpha2() : Nl80211StringAttribute(kName, kNameString) {}
+  Nl80211AttributeRegAlpha2() : NetlinkStringAttribute(kName, kNameString) {}
 };
 
-class Nl80211AttributeWiphyName : public Nl80211StringAttribute {
+class Nl80211AttributeWiphyName : public NetlinkStringAttribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
-  Nl80211AttributeWiphyName() : Nl80211StringAttribute(kName, kNameString) {}
+  Nl80211AttributeWiphyName() : NetlinkStringAttribute(kName, kNameString) {}
 };
 
 // Nested.
 
-class Nl80211NestedAttribute : public Nl80211Attribute {
+class NetlinkNestedAttribute : public NetlinkAttribute {
  public:
   static const char kMyTypeString[];
   static const Type kType;
-  Nl80211NestedAttribute(int id, const char *id_string);
+  NetlinkNestedAttribute(int id, const char *id_string);
   bool InitFromNlAttr(const nlattr *data) {
     LOG(FATAL) << "Try initializing a _specific_ nested type, instead.";
     return false;
@@ -405,9 +410,9 @@
   AttributeList value_;
 };
 
-class Nl80211AttributeCqm : public Nl80211NestedAttribute {
+class Nl80211AttributeCqm : public NetlinkNestedAttribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
   Nl80211AttributeCqm();
   bool InitFromNlAttr(const nlattr *data);
@@ -416,12 +421,12 @@
   }
 };
 
-class Nl80211AttributeStaInfo : public Nl80211NestedAttribute {
+class Nl80211AttributeStaInfo : public NetlinkNestedAttribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
   explicit Nl80211AttributeStaInfo() :
-    Nl80211NestedAttribute(kName, kNameString) {}
+    NetlinkNestedAttribute(kName, kNameString) {}
   bool InitFromNlAttr(const nlattr *const_data);
   bool ToString(std::string *value) const {
     return false;  // TODO(wdg): Need |ToString|.
@@ -430,12 +435,12 @@
 
 // Raw.
 
-class Nl80211RawAttribute : public Nl80211Attribute {
+class NetlinkRawAttribute : public NetlinkAttribute {
  public:
   static const char kMyTypeString[];
   static const Type kType;
-  Nl80211RawAttribute(int id, const char *id_string)
-      : Nl80211Attribute(id, id_string, kType, kMyTypeString) {}
+  NetlinkRawAttribute(int id, const char *id_string)
+      : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
   bool InitFromNlAttr(const nlattr *data);
   bool GetRawValue(ByteString *value) const;
   // Not supporting 'set' for raw data.  This type is a "don't know" type to
@@ -448,55 +453,55 @@
   }
 };
 
-class Nl80211AttributeFrame : public Nl80211RawAttribute {
+class Nl80211AttributeFrame : public NetlinkRawAttribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
-  Nl80211AttributeFrame() : Nl80211RawAttribute(kName, kNameString) {}
+  Nl80211AttributeFrame() : NetlinkRawAttribute(kName, kNameString) {}
 };
 
-class Nl80211AttributeGeneric : public Nl80211RawAttribute {
+class NetlinkAttributeGeneric : public NetlinkRawAttribute {
  public:
-  explicit Nl80211AttributeGeneric(nl80211_attrs id);
+  explicit NetlinkAttributeGeneric(int id);
   const char *id_string() const;
 
  private:
   std::string id_string_;
 };
 
-class Nl80211AttributeKeySeq : public Nl80211RawAttribute {
+class Nl80211AttributeKeySeq : public NetlinkRawAttribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
-  Nl80211AttributeKeySeq() : Nl80211RawAttribute(kName, kNameString) {}
+  Nl80211AttributeKeySeq() : NetlinkRawAttribute(kName, kNameString) {}
 };
 
-class Nl80211AttributeMac : public Nl80211RawAttribute {
+class Nl80211AttributeMac : public NetlinkRawAttribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
-  Nl80211AttributeMac() : Nl80211RawAttribute(kName, kNameString) {}
+  Nl80211AttributeMac() : NetlinkRawAttribute(kName, kNameString) {}
 };
 
-class Nl80211AttributeRespIe : public Nl80211RawAttribute {
+class Nl80211AttributeRespIe : public NetlinkRawAttribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
-  Nl80211AttributeRespIe() : Nl80211RawAttribute(kName, kNameString) {}
+  Nl80211AttributeRespIe() : NetlinkRawAttribute(kName, kNameString) {}
 };
 
-class Nl80211AttributeScanFrequencies : public Nl80211RawAttribute {
+class Nl80211AttributeScanFrequencies : public NetlinkRawAttribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
-  Nl80211AttributeScanFrequencies() : Nl80211RawAttribute(kName, kNameString) {}
+  Nl80211AttributeScanFrequencies() : NetlinkRawAttribute(kName, kNameString) {}
 };
 
-class Nl80211AttributeScanSsids : public Nl80211RawAttribute {
+class Nl80211AttributeScanSsids : public NetlinkRawAttribute {
  public:
-  static const nl80211_attrs kName;
+  static const int kName;
   static const char kNameString[];
-  Nl80211AttributeScanSsids() : Nl80211RawAttribute(kName, kNameString) {}
+  Nl80211AttributeScanSsids() : NetlinkRawAttribute(kName, kNameString) {}
 };
 
 
diff --git a/nl80211_message.cc b/nl80211_message.cc
index 952ada6..4b5ef2c 100644
--- a/nl80211_message.cc
+++ b/nl80211_message.cc
@@ -41,6 +41,7 @@
 #include <iomanip>
 #include <string>
 
+#include <base/bind.h>
 #include <base/format_macros.h>
 #include <base/stl_util.h>
 #include <base/stringprintf.h>
@@ -53,6 +54,7 @@
 #include "shill/scope_logger.h"
 #include "shill/wifi.h"
 
+using base::Bind;
 using base::LazyInstance;
 using base::StringAppendF;
 using base::StringPrintf;
@@ -140,8 +142,8 @@
     if (tb[i]) {
       // TODO(wdg): When Nl80211Messages instantiate their own attributes,
       // this call should, instead, call |SetAttributeFromNlAttr|.
-      attributes_.CreateAndInitFromNlAttr(static_cast<enum nl80211_attrs>(i),
-                                          tb[i]);
+      attributes_.CreateAndInitAttribute(
+          i, tb[i], Bind(&NetlinkAttribute::NewNl80211AttributeFromId));
     }
   }
 
@@ -393,8 +395,7 @@
 }
 
 // Helper function to provide a string for a MAC address.
-bool Nl80211Message::GetMacAttributeString(nl80211_attrs id,
-                                           string *value) const {
+bool Nl80211Message::GetMacAttributeString(int id, string *value) const {
   if (!value) {
     LOG(ERROR) << "Null |value| parameter";
     return false;
@@ -412,7 +413,7 @@
 
 // Helper function to provide a string for NL80211_ATTR_SCAN_FREQUENCIES.
 bool Nl80211Message::GetScanFrequenciesAttribute(
-    nl80211_attrs id, vector<uint32_t> *value) const {
+    int id, vector<uint32_t> *value) const {
   if (!value) {
     LOG(ERROR) << "Null |value| parameter";
     return false;
@@ -431,14 +432,14 @@
   int len = rawdata.GetLength();
 
   nla_for_each_attr(nst, attr_data, len, rem_nst) {
-    value->push_back(Nl80211Attribute::NlaGetU32(nst));
+    value->push_back(NetlinkAttribute::NlaGetU32(nst));
   }
   return true;
 }
 
 // Helper function to provide a string for NL80211_ATTR_SCAN_SSIDS.
 bool Nl80211Message::GetScanSsidsAttribute(
-    nl80211_attrs id, vector<string> *value) const {
+    int id, vector<string> *value) const {
   if (!value) {
     LOG(ERROR) << "Null |value| parameter";
     return false;
@@ -490,7 +491,7 @@
   return output;
 }
 
-string Nl80211Message::StringFromFrame(nl80211_attrs attr_name) const {
+string Nl80211Message::StringFromFrame(int attr_name) const {
   string output;
   ByteString frame_data;
   if (attributes().GetRawAttributeValue(attr_name,
diff --git a/nl80211_message.h b/nl80211_message.h
index fbae285..ca2f772 100644
--- a/nl80211_message.h
+++ b/nl80211_message.h
@@ -52,19 +52,17 @@
   // Helper function to provide a string for a MAC address.  If no attribute
   // is found, this method returns 'false'.  On any error with a non-NULL
   // |value|, this method sets |value| to a bogus MAC address.
-  bool GetMacAttributeString(nl80211_attrs id, std::string *value) const;
+  bool GetMacAttributeString(int id, std::string *value) const;
 
   // TODO(wdg): This needs to be moved to AttributeScanFrequencies.
   // Helper function to provide a vector of scan frequencies for attributes
   // that contain them (such as NL80211_ATTR_SCAN_FREQUENCIES).
-  bool GetScanFrequenciesAttribute(nl80211_attrs id,
-                                   std::vector<uint32_t> *value) const;
+  bool GetScanFrequenciesAttribute(int id, std::vector<uint32_t> *value) const;
 
   // TODO(wdg): This needs to be moved to AttributeScanSSids.
   // Helper function to provide a vector of SSIDs for attributes that contain
   // them (such as NL80211_ATTR_SCAN_SSIDS).
-  bool GetScanSsidsAttribute(nl80211_attrs id,
-                             std::vector<std::string> *value) const;
+  bool GetScanSsidsAttribute(int id, std::vector<std::string> *value) const;
 
   // TODO(wdg): This needs to be moved to AttributeMac.
   // Stringizes the MAC address found in 'arg'.  If there are problems (such
@@ -91,7 +89,7 @@
 
   // Returns a string that describes the contents of the frame pointed to by
   // 'attr'.
-  std::string StringFromFrame(nl80211_attrs attr_name) const;
+  std::string StringFromFrame(int attr_name) const;
 
   // Converts key_type to a string.
   static std::string StringFromKeyType(nl80211_key_type key_type);