blob: 43e4575d5c86c07ea382c26ad9b4979f29fbd3c4 [file] [log] [blame]
Wade Guthrief162f8b2013-02-27 14:13:55 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef SHILL_NETLINK_ATTRIBUTE_H_
6#define SHILL_NETLINK_ATTRIBUTE_H_
7
8#include <netlink/attr.h>
9
10#include <string>
11
Wade Guthrie89e6cb32013-03-07 08:03:45 -080012#include <base/basictypes.h>
Wade Guthrief162f8b2013-02-27 14:13:55 -080013
14#include "shill/attribute_list.h"
15#include "shill/byte_string.h"
16#include "shill/logging.h"
17#include "shill/refptr_types.h"
18
19struct nlattr;
20
21namespace shill {
22
23// NetlinkAttribute is an abstract base class that describes an attribute in a
24// netlink-80211 message. Child classes are type-specific and will define
25// Get*Value and Set*Value methods (where * is the type). A second-level of
26// child classes exist for each individual attribute type.
27//
28// An attribute has an id (which is really an enumerated value), a data type,
29// and a value. In an nlattr (the underlying format for an attribute in a
30// message), the data is stored as a blob without type information; the writer
31// and reader of the attribute must agree on the data type.
32class NetlinkAttribute {
33 public:
34 enum Type {
35 kTypeU8,
36 kTypeU16,
37 kTypeU32,
38 kTypeU64,
39 kTypeFlag,
40 kTypeString,
41 kTypeNested,
42 kTypeRaw,
43 kTypeError
44 };
45
46 NetlinkAttribute(int id, const char *id_string,
47 Type datatype, const char *datatype_string);
48 virtual ~NetlinkAttribute() {}
49
50 // Static factories generate the appropriate attribute object from the
51 // raw nlattr data.
52 static NetlinkAttribute *NewControlAttributeFromId(int id);
53 static NetlinkAttribute *NewNl80211AttributeFromId(int id);
54
55 virtual bool InitFromNlAttr(const nlattr *data);
56
57 // Accessors for the attribute's id and datatype information.
58 int id() const { return id_; }
59 virtual const char *id_string() const { return id_string_.c_str(); }
60 Type datatype() const { return datatype_; }
61 const char *datatype_string() const { return datatype_string_; }
62
63 // Accessors. Return false if request is made on wrong type of attribute.
64 virtual bool GetU8Value(uint8_t *value) const;
65 virtual bool SetU8Value(uint8_t new_value);
66
67 virtual bool GetU16Value(uint16_t *value) const;
68 virtual bool SetU16Value(uint16_t value);
69
70 virtual bool GetU32Value(uint32_t *value) const;
71 virtual bool SetU32Value(uint32_t value);
72
73 virtual bool GetU64Value(uint64_t *value) const;
74 virtual bool SetU64Value(uint64_t value);
75
76 virtual bool GetFlagValue(bool *value) const;
77 virtual bool SetFlagValue(bool value);
78
79 virtual bool GetStringValue(std::string *value) const;
80 virtual bool SetStringValue(const std::string value);
81
82 virtual bool GetNestedAttributeList(AttributeListRefPtr *value);
83 virtual bool ConstGetNestedAttributeList(
84 AttributeListConstRefPtr *value) const;
85 virtual bool SetNestedHasAValue();
86
87 virtual bool GetRawValue(ByteString *value) const;
88 virtual bool SetRawValue(const ByteString value);
89
90 // Prints the attribute info -- for debugging.
91 virtual void Print(int log_level, int indent) const;
92
93 // Fill a string with characters that represents the value of the attribute.
94 // If no attribute is found or if the datatype isn't trivially stringizable,
95 // this method returns 'false' and |value| remains unchanged.
96 virtual bool ToString(std::string *value) const = 0;
97
98 // Writes the raw attribute data to a string. For debug.
99 std::string RawToString() const;
100
101 // Encodes the attribute suitably for the attributes in the payload portion
102 // of a netlink message suitable for Sockets::Send. Return value is empty on
103 // failure.
104 virtual ByteString Encode() const = 0;
105
106 bool has_a_value() const { return has_a_value_; }
107
108 // Wrappers for libnl parsers. Needed because, while |nla_get_*| don't
109 // change their arguments, these methods don't declare themselves as 'const'.
110 static char *NlaGetString(const nlattr *input) {
111 return nla_get_string(const_cast<nlattr *>(input));
112 }
113 static uint8_t NlaGetU8(const nlattr *input) {
114 return nla_get_u8(const_cast<nlattr *>(input));
115 }
116 static uint16_t NlaGetU16(const nlattr *input) {
117 return nla_get_u16(const_cast<nlattr *>(input));
118 }
119 static uint32_t NlaGetU32(const nlattr *input) {
120 return nla_get_u32(const_cast<nlattr *>(input));
121 }
122 static uint64_t NlaGetU64(const nlattr *input) {
123 return nla_get_u64(const_cast<nlattr *>(input));
124 }
125
126 protected:
127 // Builds a string to precede a printout of this attribute.
128 std::string HeaderToPrint(int indent) const;
129
130 // Encodes the attribute suitably for the attributes in the payload portion
131 // of a netlink message suitable for Sockets::Send. Return value is empty on
132 // failure.
133 ByteString EncodeGeneric(const unsigned char *data, size_t num_bytes) const;
134
135 // Attribute data (NOT including the nlattr header) corresponding to the
136 // value in any of the child classes.
137 ByteString data_;
138
139 // True if a value has been assigned to the attribute; false, otherwise.
140 bool has_a_value_;
141
142 private:
143 int id_;
144 std::string id_string_;
145 Type datatype_;
146 const char *datatype_string_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800147
148 DISALLOW_COPY_AND_ASSIGN(NetlinkAttribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800149};
150
151class NetlinkU8Attribute : public NetlinkAttribute {
152 public:
153 static const char kMyTypeString[];
154 static const Type kType;
155 NetlinkU8Attribute(int id, const char *id_string)
156 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
157 virtual bool InitFromNlAttr(const nlattr *data);
158 virtual bool GetU8Value(uint8_t *value) const;
159 virtual bool SetU8Value(uint8_t new_value);
160 virtual bool ToString(std::string *value) const;
161 virtual ByteString Encode() const;
162
163 private:
164 uint8_t value_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800165
166 DISALLOW_COPY_AND_ASSIGN(NetlinkU8Attribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800167};
168
169class NetlinkU16Attribute : public NetlinkAttribute {
170 public:
171 static const char kMyTypeString[];
172 static const Type kType;
173 NetlinkU16Attribute(int id, const char *id_string)
174 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
175 virtual bool InitFromNlAttr(const nlattr *data);
176 virtual bool GetU16Value(uint16_t *value) const;
177 virtual bool SetU16Value(uint16_t new_value);
178 virtual bool ToString(std::string *value) const;
179 virtual ByteString Encode() const;
180
181 private:
182 uint16_t value_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800183
184 DISALLOW_COPY_AND_ASSIGN(NetlinkU16Attribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800185};
186
187class NetlinkU32Attribute : public NetlinkAttribute {
188 public:
189 static const char kMyTypeString[];
190 static const Type kType;
191 NetlinkU32Attribute(int id, const char *id_string)
192 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
193 virtual bool InitFromNlAttr(const nlattr *data);
194 virtual bool GetU32Value(uint32_t *value) const;
195 virtual bool SetU32Value(uint32_t new_value);
196 virtual bool ToString(std::string *value) const;
197 virtual ByteString Encode() const;
198
199 private:
200 uint32_t value_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800201
202 DISALLOW_COPY_AND_ASSIGN(NetlinkU32Attribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800203};
204
205class NetlinkU64Attribute : public NetlinkAttribute {
206 public:
207 static const char kMyTypeString[];
208 static const Type kType;
209 NetlinkU64Attribute(int id, const char *id_string)
210 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
211 virtual bool InitFromNlAttr(const nlattr *data);
212 virtual bool GetU64Value(uint64_t *value) const;
213 virtual bool SetU64Value(uint64_t new_value);
214 virtual bool ToString(std::string *value) const;
215 virtual ByteString Encode() const;
216
217 private:
218 uint64_t value_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800219
220 DISALLOW_COPY_AND_ASSIGN(NetlinkU64Attribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800221};
222
223class NetlinkFlagAttribute : public NetlinkAttribute {
224 public:
225 static const char kMyTypeString[];
226 static const Type kType;
227 NetlinkFlagAttribute(int id, const char *id_string)
228 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
229 virtual bool InitFromNlAttr(const nlattr *data);
230 virtual bool GetFlagValue(bool *value) const;
231 virtual bool SetFlagValue(bool new_value);
232 virtual bool ToString(std::string *value) const;
233 virtual ByteString Encode() const;
234
235 private:
236 bool value_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800237
238 DISALLOW_COPY_AND_ASSIGN(NetlinkFlagAttribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800239};
240
241class NetlinkStringAttribute : public NetlinkAttribute {
242 public:
243 static const char kMyTypeString[];
244 static const Type kType;
245 NetlinkStringAttribute(int id, const char *id_string)
246 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
247 virtual bool InitFromNlAttr(const nlattr *data);
248 virtual bool GetStringValue(std::string *value) const;
249 virtual bool SetStringValue(const std::string new_value);
250 virtual bool ToString(std::string *value) const;
251 virtual ByteString Encode() const;
Wade Guthrief54872f2013-04-11 15:11:50 -0700252 std::string value() const { return value_; }
253 void set_value(const std::string &value) { value_ = value; }
Wade Guthrief162f8b2013-02-27 14:13:55 -0800254
255 private:
256 std::string value_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800257 DISALLOW_COPY_AND_ASSIGN(NetlinkStringAttribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800258};
259
Wade Guthrief54872f2013-04-11 15:11:50 -0700260// SSID attributes are just string attributes with different output semantics.
261class NetlinkSsidAttribute : public NetlinkStringAttribute {
262 public:
263 NetlinkSsidAttribute(int id, const char *id_string)
264 : NetlinkStringAttribute(id, id_string) {}
265
266 // NOTE: |ToString| or |Print| must be used for logging to allow scrubbing.
267 virtual bool ToString(std::string *output) const;
268
269 private:
270 DISALLOW_COPY_AND_ASSIGN(NetlinkSsidAttribute);
271};
272
Wade Guthrief162f8b2013-02-27 14:13:55 -0800273class NetlinkNestedAttribute : public NetlinkAttribute {
274 public:
275 static const char kMyTypeString[];
276 static const Type kType;
277 NetlinkNestedAttribute(int id, const char *id_string);
Wade Guthrief1b36412013-04-11 14:51:31 -0700278 virtual bool InitFromNlAttr(const nlattr *data);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800279 virtual bool GetNestedAttributeList(AttributeListRefPtr *value);
280 virtual bool ConstGetNestedAttributeList(
281 AttributeListConstRefPtr *value) const;
282 virtual bool SetNestedHasAValue();
283 virtual void Print(int log_level, int indent) const;
284 virtual bool ToString(std::string *value) const;
285 virtual ByteString Encode() const;
286
287 protected:
288 // Describes a single nested attribute. Provides the expected values and
289 // type (including further nesting). Normally, an array of these, one for
290 // each attribute at one level of nesting is presented, along with the data
291 // to be parsed, to |InitNestedFromNlAttr|. If the attributes on one level
292 // represent an array, a single |NestedData| is provided and |is_array| is
293 // set (note that one level of nesting either contains _only_ an array or
294 // _no_ array).
295 struct NestedData {
Wade Guthrief1b36412013-04-11 14:51:31 -0700296 typedef base::Callback<bool (AttributeList *list, size_t id,
297 const std::string &attribute_name,
298 ByteString data)> AttributeParser;
299 typedef std::vector<NestedData> NestedDataVector;
300
301 NestedData();
302 NestedData(uint16_t type, std::string attribute_name, bool is_array);
303 NestedData(uint16_t type, std::string attribute_name, bool is_array,
304 const AttributeParser &parse_attribute);
305 uint16_t type;
306 std::string attribute_name;
307 NestedDataVector deeper_nesting;
Wade Guthrief162f8b2013-02-27 14:13:55 -0800308 bool is_array;
Wade Guthrief1b36412013-04-11 14:51:31 -0700309 // Closure that overrides the usual parsing of this attribute. A non-NULL
310 // value for |parse_attribute| will cause the software to ignore the other
311 // members of the |NestedData| structure.
312 AttributeParser parse_attribute;
Wade Guthrief162f8b2013-02-27 14:13:55 -0800313 };
314
Wade Guthrief1b36412013-04-11 14:51:31 -0700315 NestedData::NestedDataVector nested_template_;
316
Wade Guthrief162f8b2013-02-27 14:13:55 -0800317 // Builds an AttributeList (|list|) that contains all of the attriubtes in
318 // |const_data|. |const_data| should point to the enclosing nested attribute
319 // header; for the example of the nested attribute NL80211_ATTR_CQM:
320 // nlattr::nla_type: NL80211_ATTR_CQM <-- const_data points here
321 // nlattr::nla_len: 12 bytes
322 // nlattr::nla_type: PKT_LOSS_EVENT (1st and only nested attribute)
323 // nlattr::nla_len: 8 bytes
324 // <data>: 0x32
325 // One can assemble (hence, disassemble) a set of child attributes under a
326 // nested attribute parent as an array of elements or as a structure.
327 //
328 // The data is parsed using the expected configuration in |nested_template|.
329 // If the code expects an array, it will pass a single template element and
330 // mark that as an array.
Wade Guthrief1b36412013-04-11 14:51:31 -0700331 static bool InitNestedFromNlAttr(
332 AttributeList *list, const NestedData::NestedDataVector &templates,
333 const nlattr *const_data);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800334
Wade Guthrief1b36412013-04-11 14:51:31 -0700335 static bool ParseNestedArray(
336 AttributeList *list, const NestedData &templates,
337 const nlattr *const_data);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800338
Wade Guthrief1b36412013-04-11 14:51:31 -0700339 static bool ParseNestedStructure(
340 AttributeList *list, const NestedData::NestedDataVector &templates,
341 const nlattr *const_data);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800342
343 // Helper function used by InitNestedFromNlAttr to add a single child
344 // attribute to a nested attribute.
345 static void AddAttributeToNested(AttributeList *list, uint16_t type, size_t i,
346 const std::string &attribute_name,
347 const nlattr &attr,
348 const NestedData &nested_data);
349 AttributeListRefPtr value_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800350
351 private:
352 DISALLOW_COPY_AND_ASSIGN(NetlinkNestedAttribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800353};
354
355class NetlinkRawAttribute : public NetlinkAttribute {
356 public:
357 static const char kMyTypeString[];
358 static const Type kType;
359 NetlinkRawAttribute(int id, const char *id_string)
360 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
361 virtual bool InitFromNlAttr(const nlattr *data);
362 // Gets the value of the data (the header is not stored).
363 virtual bool GetRawValue(ByteString *value) const;
364 // Should set the value of the data (not the attribute header).
365 virtual bool SetRawValue(const ByteString value);
366 virtual bool ToString(std::string *value) const;
367 virtual ByteString Encode() const;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800368
369 private:
370 DISALLOW_COPY_AND_ASSIGN(NetlinkRawAttribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800371};
372
373class NetlinkAttributeGeneric : public NetlinkRawAttribute {
374 public:
375 explicit NetlinkAttributeGeneric(int id);
376 virtual const char *id_string() const;
377
378 private:
379 std::string id_string_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800380
381 DISALLOW_COPY_AND_ASSIGN(NetlinkAttributeGeneric);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800382};
383
384} // namespace shill
385
386#endif // SHILL_NETLINK_ATTRIBUTE_H_