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_