Home | History | Annotate | Download | only in net
      1 //
      2 // Copyright (C) 2012 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #ifndef SHILL_NET_NETLINK_ATTRIBUTE_H_
     18 #define SHILL_NET_NETLINK_ATTRIBUTE_H_
     19 
     20 #include <map>
     21 #include <string>
     22 #include <utility>
     23 #include <vector>
     24 
     25 #include <base/macros.h>
     26 
     27 #include "shill/net/attribute_list.h"
     28 #include "shill/net/byte_string.h"
     29 #include "shill/net/netlink_message.h"
     30 
     31 struct nlattr;
     32 
     33 namespace shill {
     34 
     35 // NetlinkAttribute is an abstract base class that describes an attribute in a
     36 // netlink-80211 message.  Child classes are type-specific and will define
     37 // Get*Value and Set*Value methods (where * is the type).  A second-level of
     38 // child classes exist for each individual attribute type.
     39 //
     40 // An attribute has an id (which is really an enumerated value), a data type,
     41 // and a value.  In an nlattr (the underlying format for an attribute in a
     42 // message), the data is stored as a blob without type information; the writer
     43 // and reader of the attribute must agree on the data type.
     44 class SHILL_EXPORT NetlinkAttribute {
     45  public:
     46   enum Type {
     47     kTypeU8,
     48     kTypeU16,
     49     kTypeU32,
     50     kTypeU64,
     51     kTypeFlag,
     52     kTypeString,
     53     kTypeNested,
     54     kTypeRaw,
     55     kTypeError
     56   };
     57 
     58   NetlinkAttribute(int id, const char* id_string,
     59                    Type datatype, const char* datatype_string);
     60   virtual ~NetlinkAttribute() {}
     61 
     62   // Static factories generate the appropriate attribute object from the
     63   // raw nlattr data.
     64   static NetlinkAttribute* NewControlAttributeFromId(int id);
     65   static NetlinkAttribute* NewNl80211AttributeFromId(
     66       NetlinkMessage::MessageContext context, int id);
     67 
     68   virtual bool InitFromValue(const ByteString& input);
     69 
     70   // Accessors for the attribute's id and datatype information.
     71   int id() const { return id_; }
     72   virtual const char* id_string() const { return id_string_.c_str(); }
     73   Type datatype() const { return datatype_; }
     74   const char* datatype_string() const { return datatype_string_; }
     75 
     76   // Accessors.  Return false if request is made on wrong type of attribute.
     77   virtual bool GetU8Value(uint8_t* value) const;
     78   virtual bool SetU8Value(uint8_t new_value);
     79 
     80   virtual bool GetU16Value(uint16_t* value) const;
     81   virtual bool SetU16Value(uint16_t value);
     82 
     83   virtual bool GetU32Value(uint32_t* value) const;
     84   virtual bool SetU32Value(uint32_t value);
     85 
     86   virtual bool GetU64Value(uint64_t* value) const;
     87   virtual bool SetU64Value(uint64_t value);
     88 
     89   virtual bool GetFlagValue(bool* value) const;
     90   virtual bool SetFlagValue(bool value);
     91 
     92   virtual bool GetStringValue(std::string* value) const;
     93   virtual bool SetStringValue(const std::string value);
     94 
     95   virtual bool GetNestedAttributeList(AttributeListRefPtr* value);
     96   virtual bool ConstGetNestedAttributeList(
     97       AttributeListConstRefPtr* value) const;
     98   virtual bool SetNestedHasAValue();
     99 
    100   virtual bool GetRawValue(ByteString* value) const;
    101   virtual bool SetRawValue(const ByteString value);
    102 
    103   // Prints the attribute info -- for debugging.
    104   virtual void Print(int log_level, int indent) const;
    105 
    106   // Fill a string with characters that represents the value of the attribute.
    107   // If no attribute is found or if the datatype isn't trivially stringizable,
    108   // this method returns 'false' and |value| remains unchanged.
    109   virtual bool ToString(std::string* value) const = 0;
    110 
    111   // Writes the raw attribute data to a string.  For debug.
    112   std::string RawToString() const;
    113 
    114   // Encodes the attribute suitably for the attributes in the payload portion
    115   // of a netlink message suitable for Sockets::Send.  Return value is empty on
    116   // failure.
    117   virtual ByteString Encode() const = 0;
    118 
    119   bool has_a_value() const { return has_a_value_; }
    120 
    121  protected:
    122   // Builds a string to precede a printout of this attribute.
    123   std::string HeaderToPrint(int indent) const;
    124 
    125   // Encodes the attribute suitably for the attributes in the payload portion
    126   // of a netlink message suitable for Sockets::Send.  Return value is empty on
    127   // failure.
    128   ByteString EncodeGeneric(const unsigned char* data, size_t num_bytes) const;
    129 
    130   // Attribute data (NOT including the nlattr header) corresponding to the
    131   // value in any of the child classes.
    132   ByteString data_;
    133 
    134   // True if a value has been assigned to the attribute; false, otherwise.
    135   bool has_a_value_;
    136 
    137  private:
    138   int id_;
    139   std::string id_string_;
    140   Type datatype_;
    141   const char* datatype_string_;
    142 
    143   DISALLOW_COPY_AND_ASSIGN(NetlinkAttribute);
    144 };
    145 
    146 class NetlinkU8Attribute : public NetlinkAttribute {
    147  public:
    148   static const char kMyTypeString[];
    149   static const Type kType;
    150   NetlinkU8Attribute(int id, const char* id_string)
    151       : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
    152   virtual bool InitFromValue(const ByteString& data);
    153   virtual bool GetU8Value(uint8_t* value) const;
    154   virtual bool SetU8Value(uint8_t new_value);
    155   virtual bool ToString(std::string* value) const;
    156   virtual ByteString Encode() const;
    157 
    158  private:
    159   uint8_t value_;
    160 
    161   DISALLOW_COPY_AND_ASSIGN(NetlinkU8Attribute);
    162 };
    163 
    164 class NetlinkU16Attribute : public NetlinkAttribute {
    165  public:
    166   static const char kMyTypeString[];
    167   static const Type kType;
    168   NetlinkU16Attribute(int id, const char* id_string)
    169       : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
    170   virtual bool InitFromValue(const ByteString& data);
    171   virtual bool GetU16Value(uint16_t* value) const;
    172   virtual bool SetU16Value(uint16_t new_value);
    173   virtual bool ToString(std::string* value) const;
    174   virtual ByteString Encode() const;
    175 
    176  private:
    177   uint16_t value_;
    178 
    179   DISALLOW_COPY_AND_ASSIGN(NetlinkU16Attribute);
    180 };
    181 
    182 // Set SHILL_EXPORT to allow unit tests to instantiate these.
    183 class SHILL_EXPORT NetlinkU32Attribute : public NetlinkAttribute {
    184  public:
    185   static const char kMyTypeString[];
    186   static const Type kType;
    187   NetlinkU32Attribute(int id, const char* id_string)
    188       : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
    189   virtual bool InitFromValue(const ByteString& data);
    190   virtual bool GetU32Value(uint32_t* value) const;
    191   virtual bool SetU32Value(uint32_t new_value);
    192   virtual bool ToString(std::string* value) const;
    193   virtual ByteString Encode() const;
    194 
    195  private:
    196   uint32_t value_;
    197 
    198   DISALLOW_COPY_AND_ASSIGN(NetlinkU32Attribute);
    199 };
    200 
    201 class NetlinkU64Attribute : public NetlinkAttribute {
    202  public:
    203   static const char kMyTypeString[];
    204   static const Type kType;
    205   NetlinkU64Attribute(int id, const char* id_string)
    206       : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
    207   virtual bool InitFromValue(const ByteString& data);
    208   virtual bool GetU64Value(uint64_t* value) const;
    209   virtual bool SetU64Value(uint64_t new_value);
    210   virtual bool ToString(std::string* value) const;
    211   virtual ByteString Encode() const;
    212 
    213  private:
    214   uint64_t value_;
    215 
    216   DISALLOW_COPY_AND_ASSIGN(NetlinkU64Attribute);
    217 };
    218 
    219 class NetlinkFlagAttribute : public NetlinkAttribute {
    220  public:
    221   static const char kMyTypeString[];
    222   static const Type kType;
    223   NetlinkFlagAttribute(int id, const char* id_string)
    224       : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
    225   virtual bool InitFromValue(const ByteString& data);
    226   virtual bool GetFlagValue(bool* value) const;
    227   virtual bool SetFlagValue(bool new_value);
    228   virtual bool ToString(std::string* value) const;
    229   virtual ByteString Encode() const;
    230 
    231  private:
    232   bool value_;
    233 
    234   DISALLOW_COPY_AND_ASSIGN(NetlinkFlagAttribute);
    235 };
    236 
    237 // Set SHILL_EXPORT to allow unit tests to instantiate these.
    238 class SHILL_EXPORT NetlinkStringAttribute : public NetlinkAttribute {
    239  public:
    240   static const char kMyTypeString[];
    241   static const Type kType;
    242   NetlinkStringAttribute(int id, const char* id_string)
    243       : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
    244   virtual bool InitFromValue(const ByteString& data);
    245   virtual bool GetStringValue(std::string* value) const;
    246   virtual bool SetStringValue(const std::string new_value);
    247   virtual bool ToString(std::string* value) const;
    248   virtual ByteString Encode() const;
    249   std::string value() const { return value_; }
    250   void set_value(const std::string& value) { value_ = value; }
    251 
    252  private:
    253   std::string value_;
    254   DISALLOW_COPY_AND_ASSIGN(NetlinkStringAttribute);
    255 };
    256 
    257 // SSID attributes are just string attributes with different output semantics.
    258 class NetlinkSsidAttribute : public NetlinkStringAttribute {
    259  public:
    260   NetlinkSsidAttribute(int id, const char* id_string)
    261       : NetlinkStringAttribute(id, id_string) {}
    262 
    263   // NOTE: |ToString| or |Print| must be used for logging to allow scrubbing.
    264   virtual bool ToString(std::string* output) const;
    265 
    266  private:
    267   DISALLOW_COPY_AND_ASSIGN(NetlinkSsidAttribute);
    268 };
    269 
    270 class NetlinkNestedAttribute : public NetlinkAttribute {
    271  public:
    272   static const char kMyTypeString[];
    273   static const Type kType;
    274   NetlinkNestedAttribute(int id, const char* id_string);
    275   virtual bool InitFromValue(const ByteString& data);
    276   virtual bool GetNestedAttributeList(AttributeListRefPtr* value);
    277   virtual bool ConstGetNestedAttributeList(
    278       AttributeListConstRefPtr* value) const;
    279   virtual bool SetNestedHasAValue();
    280   virtual void Print(int log_level, int indent) const;
    281   virtual bool ToString(std::string* value) const;
    282   virtual ByteString Encode() const;
    283 
    284  protected:
    285   // Describes a single nested attribute.  Provides the expected values and
    286   // type (including further nesting).  Normally, an array of these, one for
    287   // each attribute at one level of nesting is presented, along with the data
    288   // to be parsed, to |InitNestedFromValue|.  If the attributes on one level
    289   // represent an array, a single |NestedData| is provided and |is_array| is
    290   // set (note that one level of nesting either contains _only_ an array or
    291   // _no_ array).
    292   struct NestedData {
    293     typedef base::Callback<bool (AttributeList* list, size_t id,
    294                                  const std::string& attribute_name,
    295                                  ByteString data)> AttributeParser;
    296     typedef std::map<size_t, NestedData> NestedDataMap;
    297 
    298     NestedData();
    299     NestedData(Type type, std::string attribute_name, bool is_array);
    300     NestedData(Type type, std::string attribute_name, bool is_array,
    301                const AttributeParser& parse_attribute);
    302     Type type;
    303     std::string attribute_name;
    304     NestedDataMap deeper_nesting;
    305     bool is_array;
    306     // Closure that overrides the usual parsing of this attribute.  A non-NULL
    307     // value for |parse_attribute| will cause the software to ignore the other
    308     // members of the |NestedData| structure.
    309     AttributeParser parse_attribute;
    310   };
    311 
    312   typedef std::pair<size_t, NestedData> AttrDataPair;
    313 
    314   // Some Nl80211 nested attributes are containers that do not have an actual
    315   // attribute id, but are nested in another attribute as array elements.
    316   // In the underlying netlink message, these attributes exist in their own
    317   // nested layer, and take on attribute ids equal to their index in the array.
    318   // For purposes of parsing these attributes, assign them an arbitrary
    319   // attribute id.
    320   static const size_t kArrayAttrEnumVal;
    321 
    322   // Builds an AttributeList (|list|) that contains all of the attriubtes in
    323   // |value|.  |value| should contain the payload of the nested attribute
    324   // and not the nested attribute header itself; for the example of the nested
    325   // attribute NL80211_ATTR_CQM should contain:
    326   //    nlattr::nla_type: NL80211_ATTR_CQM
    327   //    nlattr::nla_len: 12 bytes
    328   //      nlattr::nla_type: PKT_LOSS_EVENT (1st and only nested attribute)
    329   //      nlattr::nla_len: 8 bytes
    330   //      <data>: 0x32
    331   // One can assemble (hence, disassemble) a set of child attributes under a
    332   // nested attribute parent as an array of elements or as a structure.
    333   //
    334   // The data is parsed using the expected configuration in |nested_template|.
    335   // If the code expects an array, it will pass a single template element and
    336   // mark that as an array.
    337   static bool InitNestedFromValue(
    338       const AttributeListRefPtr& list,
    339       const NestedData::NestedDataMap& templates,
    340       const ByteString& value);
    341 
    342   AttributeListRefPtr value_;
    343   NestedData::NestedDataMap nested_template_;
    344 
    345  private:
    346   // Helper functions used by InitNestedFromValue to add a single child
    347   // attribute to a nested attribute.
    348   static bool AddAttributeToNestedMap(
    349     const NetlinkNestedAttribute::NestedData::NestedDataMap& templates,
    350     const AttributeListRefPtr& list, int id, const ByteString& value);
    351   static bool AddAttributeToNestedArray(
    352     const NetlinkNestedAttribute::NestedData& array_template,
    353     const AttributeListRefPtr& list, int id, const ByteString& value);
    354   static bool AddAttributeToNestedInner(
    355     const NetlinkNestedAttribute::NestedData& nested_template,
    356     const std::string& attribute_name, const AttributeListRefPtr& list,
    357     int id, const ByteString& value);
    358 
    359   DISALLOW_COPY_AND_ASSIGN(NetlinkNestedAttribute);
    360 };
    361 
    362 class NetlinkRawAttribute : public NetlinkAttribute {
    363  public:
    364   static const char kMyTypeString[];
    365   static const Type kType;
    366   NetlinkRawAttribute(int id, const char* id_string)
    367       : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
    368   virtual bool InitFromValue(const ByteString& data);
    369   // Gets the value of the data (the header is not stored).
    370   virtual bool GetRawValue(ByteString* value) const;
    371   // Should set the value of the data (not the attribute header).
    372   virtual bool SetRawValue(const ByteString value);
    373   virtual bool ToString(std::string* value) const;
    374   virtual ByteString Encode() const;
    375 
    376  private:
    377   DISALLOW_COPY_AND_ASSIGN(NetlinkRawAttribute);
    378 };
    379 
    380 class NetlinkAttributeGeneric : public NetlinkRawAttribute {
    381  public:
    382   explicit NetlinkAttributeGeneric(int id);
    383   virtual const char* id_string() const;
    384 
    385  private:
    386   std::string id_string_;
    387 
    388   DISALLOW_COPY_AND_ASSIGN(NetlinkAttributeGeneric);
    389 };
    390 
    391 }  // namespace shill
    392 
    393 #endif  // SHILL_NET_NETLINK_ATTRIBUTE_H_
    394