shill: Breaks nl80211_attribute.* into files appropriate to classes.

This CL *ONLY* breaks nl80211_attribute.* into netlink_attribute.*
and nl80211_attribute.* and adds control_netlink_attribute.*.  None of
the netlink or nl80211 code should be changed, here.

BUG=None.
TEST=unittests.

Change-Id: Ia181642af052dceb280a23b5fac25a2400d93e1a
Reviewed-on: https://gerrit.chromium.org/gerrit/44255
Commit-Queue: Wade Guthrie <wdg@chromium.org>
Reviewed-by: Wade Guthrie <wdg@chromium.org>
Tested-by: Wade Guthrie <wdg@chromium.org>
diff --git a/netlink_attribute.h b/netlink_attribute.h
new file mode 100644
index 0000000..3dbfa7e
--- /dev/null
+++ b/netlink_attribute.h
@@ -0,0 +1,342 @@
+// 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.
+
+#ifndef SHILL_NETLINK_ATTRIBUTE_H_
+#define SHILL_NETLINK_ATTRIBUTE_H_
+
+#include <netlink/attr.h>
+
+#include <string>
+
+#include <base/memory/weak_ptr.h>
+
+#include "shill/attribute_list.h"
+#include "shill/byte_string.h"
+#include "shill/logging.h"
+#include "shill/refptr_types.h"
+
+struct nlattr;
+
+namespace shill {
+
+// 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.
+//
+// An attribute has an id (which is really an enumerated value), a data type,
+// 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 NetlinkAttribute {
+ public:
+  enum Type {
+    kTypeU8,
+    kTypeU16,
+    kTypeU32,
+    kTypeU64,
+    kTypeFlag,
+    kTypeString,
+    kTypeNested,
+    kTypeRaw,
+    kTypeError
+  };
+
+  NetlinkAttribute(int id, const char *id_string,
+                   Type datatype, const char *datatype_string);
+  virtual ~NetlinkAttribute() {}
+
+  // Static factories generate the appropriate attribute object from the
+  // raw nlattr data.
+  static NetlinkAttribute *NewControlAttributeFromId(int id);
+  static NetlinkAttribute *NewNl80211AttributeFromId(int id);
+
+  virtual bool InitFromNlAttr(const nlattr *data);
+
+  // Accessors for the attribute's id and datatype information.
+  int id() const { return id_; }
+  virtual const char *id_string() const { return id_string_.c_str(); }
+  Type datatype() const { return datatype_; }
+  const char *datatype_string() const { return datatype_string_; }
+
+  // Accessors.  Return false if request is made on wrong type of attribute.
+  virtual bool GetU8Value(uint8_t *value) const;
+  virtual bool SetU8Value(uint8_t new_value);
+
+  virtual bool GetU16Value(uint16_t *value) const;
+  virtual bool SetU16Value(uint16_t value);
+
+  virtual bool GetU32Value(uint32_t *value) const;
+  virtual bool SetU32Value(uint32_t value);
+
+  virtual bool GetU64Value(uint64_t *value) const;
+  virtual bool SetU64Value(uint64_t value);
+
+  virtual bool GetFlagValue(bool *value) const;
+  virtual bool SetFlagValue(bool value);
+
+  virtual bool GetStringValue(std::string *value) const;
+  virtual bool SetStringValue(const std::string value);
+
+  virtual bool GetNestedAttributeList(AttributeListRefPtr *value);
+  virtual bool ConstGetNestedAttributeList(
+      AttributeListConstRefPtr *value) const;
+  virtual bool SetNestedHasAValue();
+
+  virtual bool GetRawValue(ByteString *value) const;
+  virtual bool SetRawValue(const ByteString value);
+
+  // Prints the attribute info -- for debugging.
+  virtual void Print(int log_level, int indent) const;
+
+  // Fill a string with characters that represents the value of the attribute.
+  // 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;
+
+  bool has_a_value() const { return has_a_value_; }
+
+  // Wrappers for libnl parsers.  Needed because, while |nla_get_*| don't
+  // change their arguments, these methods don't declare themselves as 'const'.
+  static char *NlaGetString(const nlattr *input) {
+    return nla_get_string(const_cast<nlattr *>(input));
+  }
+  static uint8_t NlaGetU8(const nlattr *input) {
+    return nla_get_u8(const_cast<nlattr *>(input));
+  }
+  static uint16_t NlaGetU16(const nlattr *input) {
+    return nla_get_u16(const_cast<nlattr *>(input));
+  }
+  static uint32_t NlaGetU32(const nlattr *input) {
+    return nla_get_u32(const_cast<nlattr *>(input));
+  }
+  static uint64_t NlaGetU64(const nlattr *input) {
+    return nla_get_u64(const_cast<nlattr *>(input));
+  }
+
+ protected:
+  // Builds a string to precede a printout of this attribute.
+  std::string HeaderToPrint(int indent) 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.
+  ByteString EncodeGeneric(const unsigned char *data, size_t num_bytes) const;
+
+  // Attribute data (NOT including the nlattr header) corresponding to the
+  // value in any of the child classes.
+  ByteString data_;
+
+  // True if a value has been assigned to the attribute; false, otherwise.
+  bool has_a_value_;
+
+ private:
+  int id_;
+  std::string id_string_;
+  Type datatype_;
+  const char *datatype_string_;
+};
+
+class NetlinkU8Attribute : public NetlinkAttribute {
+ public:
+  static const char kMyTypeString[];
+  static const Type kType;
+  NetlinkU8Attribute(int id, const char *id_string)
+      : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
+  virtual bool InitFromNlAttr(const nlattr *data);
+  virtual bool GetU8Value(uint8_t *value) const;
+  virtual bool SetU8Value(uint8_t new_value);
+  virtual bool ToString(std::string *value) const;
+  virtual ByteString Encode() const;
+
+ private:
+  uint8_t value_;
+};
+
+class NetlinkU16Attribute : public NetlinkAttribute {
+ public:
+  static const char kMyTypeString[];
+  static const Type kType;
+  NetlinkU16Attribute(int id, const char *id_string)
+      : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
+  virtual bool InitFromNlAttr(const nlattr *data);
+  virtual bool GetU16Value(uint16_t *value) const;
+  virtual bool SetU16Value(uint16_t new_value);
+  virtual bool ToString(std::string *value) const;
+  virtual ByteString Encode() const;
+
+ private:
+  uint16_t value_;
+};
+
+class NetlinkU32Attribute : public NetlinkAttribute {
+ public:
+  static const char kMyTypeString[];
+  static const Type kType;
+  NetlinkU32Attribute(int id, const char *id_string)
+      : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
+  virtual bool InitFromNlAttr(const nlattr *data);
+  virtual bool GetU32Value(uint32_t *value) const;
+  virtual bool SetU32Value(uint32_t new_value);
+  virtual bool ToString(std::string *value) const;
+  virtual ByteString Encode() const;
+
+ private:
+  uint32_t value_;
+};
+
+class NetlinkU64Attribute : public NetlinkAttribute {
+ public:
+  static const char kMyTypeString[];
+  static const Type kType;
+  NetlinkU64Attribute(int id, const char *id_string)
+      : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
+  virtual bool InitFromNlAttr(const nlattr *data);
+  virtual bool GetU64Value(uint64_t *value) const;
+  virtual bool SetU64Value(uint64_t new_value);
+  virtual bool ToString(std::string *value) const;
+  virtual ByteString Encode() const;
+
+ private:
+  uint64_t value_;
+};
+
+class NetlinkFlagAttribute : public NetlinkAttribute {
+ public:
+  static const char kMyTypeString[];
+  static const Type kType;
+  NetlinkFlagAttribute(int id, const char *id_string)
+      : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
+  virtual bool InitFromNlAttr(const nlattr *data);
+  virtual bool GetFlagValue(bool *value) const;
+  virtual bool SetFlagValue(bool new_value);
+  virtual bool ToString(std::string *value) const;
+  virtual ByteString Encode() const;
+
+ private:
+  bool value_;
+};
+
+class NetlinkStringAttribute : public NetlinkAttribute {
+ public:
+  static const char kMyTypeString[];
+  static const Type kType;
+  NetlinkStringAttribute(int id, const char *id_string)
+      : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
+  virtual bool InitFromNlAttr(const nlattr *data);
+  virtual bool GetStringValue(std::string *value) const;
+  virtual bool SetStringValue(const std::string new_value);
+  virtual bool ToString(std::string *value) const;
+  virtual ByteString Encode() const;
+
+ private:
+  std::string value_;
+};
+
+class NetlinkNestedAttribute : public NetlinkAttribute {
+ public:
+  static const char kMyTypeString[];
+  static const Type kType;
+  NetlinkNestedAttribute(int id, const char *id_string);
+  virtual bool InitFromNlAttr(const nlattr *data) {
+    LOG(FATAL) << "Try initializing a _specific_ nested type, instead.";
+    return false;
+  }
+  virtual bool GetNestedAttributeList(AttributeListRefPtr *value);
+  virtual bool ConstGetNestedAttributeList(
+      AttributeListConstRefPtr *value) const;
+  virtual bool SetNestedHasAValue();
+  virtual void Print(int log_level, int indent) const;
+  virtual bool ToString(std::string *value) const;
+  virtual ByteString Encode() const;
+
+ protected:
+  // Describes a single nested attribute.  Provides the expected values and
+  // type (including further nesting).  Normally, an array of these, one for
+  // each attribute at one level of nesting is presented, along with the data
+  // to be parsed, to |InitNestedFromNlAttr|.  If the attributes on one level
+  // represent an array, a single |NestedData| is provided and |is_array| is
+  // set (note that one level of nesting either contains _only_ an array or
+  // _no_ array).
+  struct NestedData {
+    nla_policy policy;
+    const char *attribute_name;
+    const NestedData *deeper_nesting;
+    size_t deeper_nesting_size;
+    bool is_array;
+    // TODO(wdg): Add function pointer for a custom attribute parser.
+  };
+
+  // Builds an AttributeList (|list|) that contains all of the attriubtes in
+  // |const_data|.  |const_data| should point to the enclosing nested attribute
+  // header; for the example of the nested attribute NL80211_ATTR_CQM:
+  //    nlattr::nla_type: NL80211_ATTR_CQM <-- const_data points here
+  //    nlattr::nla_len: 12 bytes
+  //      nlattr::nla_type: PKT_LOSS_EVENT (1st and only nested attribute)
+  //      nlattr::nla_len: 8 bytes
+  //      <data>: 0x32
+  // One can assemble (hence, disassemble) a set of child attributes under a
+  // nested attribute parent as an array of elements or as a structure.
+  //
+  // The data is parsed using the expected configuration in |nested_template|.
+  // If the code expects an array, it will pass a single template element and
+  // mark that as an array.
+  static bool InitNestedFromNlAttr(AttributeList *list,
+                                   const NestedData *nested_template,
+                                   size_t nested_template_size,
+                                   const nlattr *const_data);
+
+  static bool ParseNestedArray(AttributeList *list,
+                               const NestedData &nested_template,
+                               const nlattr *const_data);
+
+  static bool ParseNestedStructure(AttributeList *list,
+                                   const NestedData *nested_template,
+                                   size_t nested_template_size,
+                                   const nlattr *const_data);
+
+  // Helper function used by InitNestedFromNlAttr to add a single child
+  // attribute to a nested attribute.
+  static void AddAttributeToNested(AttributeList *list, uint16_t type, size_t i,
+                                   const std::string &attribute_name,
+                                   const nlattr &attr,
+                                   const NestedData &nested_data);
+  AttributeListRefPtr value_;
+};
+
+class NetlinkRawAttribute : public NetlinkAttribute {
+ public:
+  static const char kMyTypeString[];
+  static const Type kType;
+  NetlinkRawAttribute(int id, const char *id_string)
+      : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
+  virtual bool InitFromNlAttr(const nlattr *data);
+  // Gets the value of the data (the header is not stored).
+  virtual bool GetRawValue(ByteString *value) const;
+  // Should set the value of the data (not the attribute header).
+  virtual bool SetRawValue(const ByteString value);
+  virtual bool ToString(std::string *value) const;
+  virtual ByteString Encode() const;
+};
+
+class NetlinkAttributeGeneric : public NetlinkRawAttribute {
+ public:
+  explicit NetlinkAttributeGeneric(int id);
+  virtual const char *id_string() const;
+
+ private:
+  std::string id_string_;
+};
+
+}  // namespace shill
+
+#endif  // SHILL_NETLINK_ATTRIBUTE_H_