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); ~NetlinkAttribute()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. id()71 int id() const { return id_; } id_string()72 virtual const char* id_string() const { return id_string_.c_str(); } datatype()73 Type datatype() const { return datatype_; } datatype_string()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 has_a_value()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; NetlinkU8Attribute(int id,const char * id_string)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; NetlinkU16Attribute(int id,const char * id_string)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; NetlinkU32Attribute(int id,const char * id_string)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; NetlinkU64Attribute(int id,const char * id_string)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; NetlinkFlagAttribute(int id,const char * id_string)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; NetlinkStringAttribute(int id,const char * id_string)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; value()249 std::string value() const { return value_; } set_value(const std::string & 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: NetlinkSsidAttribute(int id,const char * id_string)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; NetlinkRawAttribute(int id,const char * id_string)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