393 lines
14 KiB
C++
393 lines
14 KiB
C++
//
|
|
// Copyright (C) 2012 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
#ifndef SHILL_NET_NETLINK_ATTRIBUTE_H_
|
|
#define SHILL_NET_NETLINK_ATTRIBUTE_H_
|
|
|
|
#include <map>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include <base/macros.h>
|
|
|
|
#include "shill/net/attribute_list.h"
|
|
#include "shill/net/byte_string.h"
|
|
#include "shill/net/netlink_message.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 SHILL_EXPORT 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(
|
|
NetlinkMessage::MessageContext context, int id);
|
|
|
|
virtual bool InitFromValue(const ByteString& input);
|
|
|
|
// 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_; }
|
|
|
|
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_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(NetlinkAttribute);
|
|
};
|
|
|
|
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 InitFromValue(const ByteString& 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_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(NetlinkU8Attribute);
|
|
};
|
|
|
|
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 InitFromValue(const ByteString& 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_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(NetlinkU16Attribute);
|
|
};
|
|
|
|
// Set SHILL_EXPORT to allow unit tests to instantiate these.
|
|
class SHILL_EXPORT 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 InitFromValue(const ByteString& 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_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(NetlinkU32Attribute);
|
|
};
|
|
|
|
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 InitFromValue(const ByteString& 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_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(NetlinkU64Attribute);
|
|
};
|
|
|
|
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 InitFromValue(const ByteString& 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_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(NetlinkFlagAttribute);
|
|
};
|
|
|
|
// Set SHILL_EXPORT to allow unit tests to instantiate these.
|
|
class SHILL_EXPORT 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 InitFromValue(const ByteString& 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;
|
|
std::string value() const { return value_; }
|
|
void set_value(const std::string& value) { value_ = value; }
|
|
|
|
private:
|
|
std::string value_;
|
|
DISALLOW_COPY_AND_ASSIGN(NetlinkStringAttribute);
|
|
};
|
|
|
|
// SSID attributes are just string attributes with different output semantics.
|
|
class NetlinkSsidAttribute : public NetlinkStringAttribute {
|
|
public:
|
|
NetlinkSsidAttribute(int id, const char* id_string)
|
|
: NetlinkStringAttribute(id, id_string) {}
|
|
|
|
// NOTE: |ToString| or |Print| must be used for logging to allow scrubbing.
|
|
virtual bool ToString(std::string* output) const;
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(NetlinkSsidAttribute);
|
|
};
|
|
|
|
class NetlinkNestedAttribute : public NetlinkAttribute {
|
|
public:
|
|
static const char kMyTypeString[];
|
|
static const Type kType;
|
|
NetlinkNestedAttribute(int id, const char* id_string);
|
|
virtual bool InitFromValue(const ByteString& data);
|
|
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 |InitNestedFromValue|. 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 {
|
|
typedef base::Callback<bool (AttributeList* list, size_t id,
|
|
const std::string& attribute_name,
|
|
ByteString data)> AttributeParser;
|
|
typedef std::map<size_t, NestedData> NestedDataMap;
|
|
|
|
NestedData();
|
|
NestedData(Type type, std::string attribute_name, bool is_array);
|
|
NestedData(Type type, std::string attribute_name, bool is_array,
|
|
const AttributeParser& parse_attribute);
|
|
Type type;
|
|
std::string attribute_name;
|
|
NestedDataMap deeper_nesting;
|
|
bool is_array;
|
|
// Closure that overrides the usual parsing of this attribute. A non-NULL
|
|
// value for |parse_attribute| will cause the software to ignore the other
|
|
// members of the |NestedData| structure.
|
|
AttributeParser parse_attribute;
|
|
};
|
|
|
|
typedef std::pair<size_t, NestedData> AttrDataPair;
|
|
|
|
// Some Nl80211 nested attributes are containers that do not have an actual
|
|
// attribute id, but are nested in another attribute as array elements.
|
|
// In the underlying netlink message, these attributes exist in their own
|
|
// nested layer, and take on attribute ids equal to their index in the array.
|
|
// For purposes of parsing these attributes, assign them an arbitrary
|
|
// attribute id.
|
|
static const size_t kArrayAttrEnumVal;
|
|
|
|
// Builds an AttributeList (|list|) that contains all of the attriubtes in
|
|
// |value|. |value| should contain the payload of the nested attribute
|
|
// and not the nested attribute header itself; for the example of the nested
|
|
// attribute NL80211_ATTR_CQM should contain:
|
|
// nlattr::nla_type: NL80211_ATTR_CQM
|
|
// 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 InitNestedFromValue(
|
|
const AttributeListRefPtr& list,
|
|
const NestedData::NestedDataMap& templates,
|
|
const ByteString& value);
|
|
|
|
AttributeListRefPtr value_;
|
|
NestedData::NestedDataMap nested_template_;
|
|
|
|
private:
|
|
// Helper functions used by InitNestedFromValue to add a single child
|
|
// attribute to a nested attribute.
|
|
static bool AddAttributeToNestedMap(
|
|
const NetlinkNestedAttribute::NestedData::NestedDataMap& templates,
|
|
const AttributeListRefPtr& list, int id, const ByteString& value);
|
|
static bool AddAttributeToNestedArray(
|
|
const NetlinkNestedAttribute::NestedData& array_template,
|
|
const AttributeListRefPtr& list, int id, const ByteString& value);
|
|
static bool AddAttributeToNestedInner(
|
|
const NetlinkNestedAttribute::NestedData& nested_template,
|
|
const std::string& attribute_name, const AttributeListRefPtr& list,
|
|
int id, const ByteString& value);
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(NetlinkNestedAttribute);
|
|
};
|
|
|
|
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 InitFromValue(const ByteString& 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;
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(NetlinkRawAttribute);
|
|
};
|
|
|
|
class NetlinkAttributeGeneric : public NetlinkRawAttribute {
|
|
public:
|
|
explicit NetlinkAttributeGeneric(int id);
|
|
virtual const char* id_string() const;
|
|
|
|
private:
|
|
std::string id_string_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(NetlinkAttributeGeneric);
|
|
};
|
|
|
|
} // namespace shill
|
|
|
|
#endif // SHILL_NET_NETLINK_ATTRIBUTE_H_
|