blob: 294ffcfe700eba8e4915c4e00b7403398f0ae9c6 [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>
Alex Vakulenko8a532292014-06-16 17:18:44 -070011#include <vector>
Wade Guthrief162f8b2013-02-27 14:13:55 -080012
Wade Guthrie89e6cb32013-03-07 08:03:45 -080013#include <base/basictypes.h>
Wade Guthrief162f8b2013-02-27 14:13:55 -080014
15#include "shill/attribute_list.h"
16#include "shill/byte_string.h"
17#include "shill/logging.h"
18#include "shill/refptr_types.h"
19
20struct nlattr;
21
22namespace shill {
23
24// NetlinkAttribute is an abstract base class that describes an attribute in a
25// netlink-80211 message. Child classes are type-specific and will define
26// Get*Value and Set*Value methods (where * is the type). A second-level of
27// child classes exist for each individual attribute type.
28//
29// An attribute has an id (which is really an enumerated value), a data type,
30// and a value. In an nlattr (the underlying format for an attribute in a
31// message), the data is stored as a blob without type information; the writer
32// and reader of the attribute must agree on the data type.
33class NetlinkAttribute {
34 public:
35 enum Type {
36 kTypeU8,
37 kTypeU16,
38 kTypeU32,
39 kTypeU64,
40 kTypeFlag,
41 kTypeString,
42 kTypeNested,
43 kTypeRaw,
44 kTypeError
45 };
46
47 NetlinkAttribute(int id, const char *id_string,
48 Type datatype, const char *datatype_string);
49 virtual ~NetlinkAttribute() {}
50
51 // Static factories generate the appropriate attribute object from the
52 // raw nlattr data.
53 static NetlinkAttribute *NewControlAttributeFromId(int id);
54 static NetlinkAttribute *NewNl80211AttributeFromId(int id);
55
56 virtual bool InitFromNlAttr(const nlattr *data);
57
58 // Accessors for the attribute's id and datatype information.
59 int id() const { return id_; }
60 virtual const char *id_string() const { return id_string_.c_str(); }
61 Type datatype() const { return datatype_; }
62 const char *datatype_string() const { return datatype_string_; }
63
64 // Accessors. Return false if request is made on wrong type of attribute.
65 virtual bool GetU8Value(uint8_t *value) const;
66 virtual bool SetU8Value(uint8_t new_value);
67
68 virtual bool GetU16Value(uint16_t *value) const;
69 virtual bool SetU16Value(uint16_t value);
70
71 virtual bool GetU32Value(uint32_t *value) const;
72 virtual bool SetU32Value(uint32_t value);
73
74 virtual bool GetU64Value(uint64_t *value) const;
75 virtual bool SetU64Value(uint64_t value);
76
77 virtual bool GetFlagValue(bool *value) const;
78 virtual bool SetFlagValue(bool value);
79
80 virtual bool GetStringValue(std::string *value) const;
81 virtual bool SetStringValue(const std::string value);
82
83 virtual bool GetNestedAttributeList(AttributeListRefPtr *value);
84 virtual bool ConstGetNestedAttributeList(
85 AttributeListConstRefPtr *value) const;
86 virtual bool SetNestedHasAValue();
87
88 virtual bool GetRawValue(ByteString *value) const;
89 virtual bool SetRawValue(const ByteString value);
90
91 // Prints the attribute info -- for debugging.
92 virtual void Print(int log_level, int indent) const;
93
94 // Fill a string with characters that represents the value of the attribute.
95 // If no attribute is found or if the datatype isn't trivially stringizable,
96 // this method returns 'false' and |value| remains unchanged.
97 virtual bool ToString(std::string *value) const = 0;
98
99 // Writes the raw attribute data to a string. For debug.
100 std::string RawToString() const;
101
102 // Encodes the attribute suitably for the attributes in the payload portion
103 // of a netlink message suitable for Sockets::Send. Return value is empty on
104 // failure.
105 virtual ByteString Encode() const = 0;
106
107 bool has_a_value() const { return has_a_value_; }
108
109 // Wrappers for libnl parsers. Needed because, while |nla_get_*| don't
110 // change their arguments, these methods don't declare themselves as 'const'.
111 static char *NlaGetString(const nlattr *input) {
112 return nla_get_string(const_cast<nlattr *>(input));
113 }
114 static uint8_t NlaGetU8(const nlattr *input) {
115 return nla_get_u8(const_cast<nlattr *>(input));
116 }
117 static uint16_t NlaGetU16(const nlattr *input) {
118 return nla_get_u16(const_cast<nlattr *>(input));
119 }
120 static uint32_t NlaGetU32(const nlattr *input) {
121 return nla_get_u32(const_cast<nlattr *>(input));
122 }
123 static uint64_t NlaGetU64(const nlattr *input) {
124 return nla_get_u64(const_cast<nlattr *>(input));
125 }
126
127 protected:
128 // Builds a string to precede a printout of this attribute.
129 std::string HeaderToPrint(int indent) const;
130
131 // Encodes the attribute suitably for the attributes in the payload portion
132 // of a netlink message suitable for Sockets::Send. Return value is empty on
133 // failure.
134 ByteString EncodeGeneric(const unsigned char *data, size_t num_bytes) const;
135
136 // Attribute data (NOT including the nlattr header) corresponding to the
137 // value in any of the child classes.
138 ByteString data_;
139
140 // True if a value has been assigned to the attribute; false, otherwise.
141 bool has_a_value_;
142
143 private:
144 int id_;
145 std::string id_string_;
146 Type datatype_;
147 const char *datatype_string_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800148
149 DISALLOW_COPY_AND_ASSIGN(NetlinkAttribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800150};
151
152class NetlinkU8Attribute : public NetlinkAttribute {
153 public:
154 static const char kMyTypeString[];
155 static const Type kType;
156 NetlinkU8Attribute(int id, const char *id_string)
157 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
158 virtual bool InitFromNlAttr(const nlattr *data);
159 virtual bool GetU8Value(uint8_t *value) const;
160 virtual bool SetU8Value(uint8_t new_value);
161 virtual bool ToString(std::string *value) const;
162 virtual ByteString Encode() const;
163
164 private:
165 uint8_t value_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800166
167 DISALLOW_COPY_AND_ASSIGN(NetlinkU8Attribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800168};
169
170class NetlinkU16Attribute : public NetlinkAttribute {
171 public:
172 static const char kMyTypeString[];
173 static const Type kType;
174 NetlinkU16Attribute(int id, const char *id_string)
175 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
176 virtual bool InitFromNlAttr(const nlattr *data);
177 virtual bool GetU16Value(uint16_t *value) const;
178 virtual bool SetU16Value(uint16_t new_value);
179 virtual bool ToString(std::string *value) const;
180 virtual ByteString Encode() const;
181
182 private:
183 uint16_t value_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800184
185 DISALLOW_COPY_AND_ASSIGN(NetlinkU16Attribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800186};
187
188class NetlinkU32Attribute : public NetlinkAttribute {
189 public:
190 static const char kMyTypeString[];
191 static const Type kType;
192 NetlinkU32Attribute(int id, const char *id_string)
193 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
194 virtual bool InitFromNlAttr(const nlattr *data);
195 virtual bool GetU32Value(uint32_t *value) const;
196 virtual bool SetU32Value(uint32_t new_value);
197 virtual bool ToString(std::string *value) const;
198 virtual ByteString Encode() const;
199
200 private:
201 uint32_t value_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800202
203 DISALLOW_COPY_AND_ASSIGN(NetlinkU32Attribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800204};
205
206class NetlinkU64Attribute : public NetlinkAttribute {
207 public:
208 static const char kMyTypeString[];
209 static const Type kType;
210 NetlinkU64Attribute(int id, const char *id_string)
211 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
212 virtual bool InitFromNlAttr(const nlattr *data);
213 virtual bool GetU64Value(uint64_t *value) const;
214 virtual bool SetU64Value(uint64_t new_value);
215 virtual bool ToString(std::string *value) const;
216 virtual ByteString Encode() const;
217
218 private:
219 uint64_t value_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800220
221 DISALLOW_COPY_AND_ASSIGN(NetlinkU64Attribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800222};
223
224class NetlinkFlagAttribute : public NetlinkAttribute {
225 public:
226 static const char kMyTypeString[];
227 static const Type kType;
228 NetlinkFlagAttribute(int id, const char *id_string)
229 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
230 virtual bool InitFromNlAttr(const nlattr *data);
231 virtual bool GetFlagValue(bool *value) const;
232 virtual bool SetFlagValue(bool new_value);
233 virtual bool ToString(std::string *value) const;
234 virtual ByteString Encode() const;
235
236 private:
237 bool value_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800238
239 DISALLOW_COPY_AND_ASSIGN(NetlinkFlagAttribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800240};
241
242class NetlinkStringAttribute : public NetlinkAttribute {
243 public:
244 static const char kMyTypeString[];
245 static const Type kType;
246 NetlinkStringAttribute(int id, const char *id_string)
247 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
248 virtual bool InitFromNlAttr(const nlattr *data);
249 virtual bool GetStringValue(std::string *value) const;
250 virtual bool SetStringValue(const std::string new_value);
251 virtual bool ToString(std::string *value) const;
252 virtual ByteString Encode() const;
Wade Guthrief54872f2013-04-11 15:11:50 -0700253 std::string value() const { return value_; }
254 void set_value(const std::string &value) { value_ = value; }
Wade Guthrief162f8b2013-02-27 14:13:55 -0800255
256 private:
257 std::string value_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800258 DISALLOW_COPY_AND_ASSIGN(NetlinkStringAttribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800259};
260
Wade Guthrief54872f2013-04-11 15:11:50 -0700261// SSID attributes are just string attributes with different output semantics.
262class NetlinkSsidAttribute : public NetlinkStringAttribute {
263 public:
264 NetlinkSsidAttribute(int id, const char *id_string)
265 : NetlinkStringAttribute(id, id_string) {}
266
267 // NOTE: |ToString| or |Print| must be used for logging to allow scrubbing.
268 virtual bool ToString(std::string *output) const;
269
270 private:
271 DISALLOW_COPY_AND_ASSIGN(NetlinkSsidAttribute);
272};
273
Wade Guthrief162f8b2013-02-27 14:13:55 -0800274class NetlinkNestedAttribute : public NetlinkAttribute {
275 public:
276 static const char kMyTypeString[];
277 static const Type kType;
278 NetlinkNestedAttribute(int id, const char *id_string);
Wade Guthrief1b36412013-04-11 14:51:31 -0700279 virtual bool InitFromNlAttr(const nlattr *data);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800280 virtual bool GetNestedAttributeList(AttributeListRefPtr *value);
281 virtual bool ConstGetNestedAttributeList(
282 AttributeListConstRefPtr *value) const;
283 virtual bool SetNestedHasAValue();
284 virtual void Print(int log_level, int indent) const;
285 virtual bool ToString(std::string *value) const;
286 virtual ByteString Encode() const;
287
288 protected:
289 // Describes a single nested attribute. Provides the expected values and
290 // type (including further nesting). Normally, an array of these, one for
291 // each attribute at one level of nesting is presented, along with the data
292 // to be parsed, to |InitNestedFromNlAttr|. If the attributes on one level
293 // represent an array, a single |NestedData| is provided and |is_array| is
294 // set (note that one level of nesting either contains _only_ an array or
295 // _no_ array).
296 struct NestedData {
Wade Guthrief1b36412013-04-11 14:51:31 -0700297 typedef base::Callback<bool (AttributeList *list, size_t id,
298 const std::string &attribute_name,
299 ByteString data)> AttributeParser;
300 typedef std::vector<NestedData> NestedDataVector;
301
302 NestedData();
303 NestedData(uint16_t type, std::string attribute_name, bool is_array);
304 NestedData(uint16_t type, std::string attribute_name, bool is_array,
305 const AttributeParser &parse_attribute);
306 uint16_t type;
307 std::string attribute_name;
308 NestedDataVector deeper_nesting;
Wade Guthrief162f8b2013-02-27 14:13:55 -0800309 bool is_array;
Wade Guthrief1b36412013-04-11 14:51:31 -0700310 // Closure that overrides the usual parsing of this attribute. A non-NULL
311 // value for |parse_attribute| will cause the software to ignore the other
312 // members of the |NestedData| structure.
313 AttributeParser parse_attribute;
Wade Guthrief162f8b2013-02-27 14:13:55 -0800314 };
315
Wade Guthrief1b36412013-04-11 14:51:31 -0700316 NestedData::NestedDataVector nested_template_;
317
Wade Guthrief162f8b2013-02-27 14:13:55 -0800318 // Builds an AttributeList (|list|) that contains all of the attriubtes in
319 // |const_data|. |const_data| should point to the enclosing nested attribute
320 // header; for the example of the nested attribute NL80211_ATTR_CQM:
321 // nlattr::nla_type: NL80211_ATTR_CQM <-- const_data points here
322 // nlattr::nla_len: 12 bytes
323 // nlattr::nla_type: PKT_LOSS_EVENT (1st and only nested attribute)
324 // nlattr::nla_len: 8 bytes
325 // <data>: 0x32
326 // One can assemble (hence, disassemble) a set of child attributes under a
327 // nested attribute parent as an array of elements or as a structure.
328 //
329 // The data is parsed using the expected configuration in |nested_template|.
330 // If the code expects an array, it will pass a single template element and
331 // mark that as an array.
Wade Guthrief1b36412013-04-11 14:51:31 -0700332 static bool InitNestedFromNlAttr(
333 AttributeList *list, const NestedData::NestedDataVector &templates,
334 const nlattr *const_data);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800335
Wade Guthrief1b36412013-04-11 14:51:31 -0700336 static bool ParseNestedArray(
337 AttributeList *list, const NestedData &templates,
338 const nlattr *const_data);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800339
Wade Guthrief1b36412013-04-11 14:51:31 -0700340 static bool ParseNestedStructure(
341 AttributeList *list, const NestedData::NestedDataVector &templates,
342 const nlattr *const_data);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800343
344 // Helper function used by InitNestedFromNlAttr to add a single child
345 // attribute to a nested attribute.
346 static void AddAttributeToNested(AttributeList *list, uint16_t type, size_t i,
347 const std::string &attribute_name,
348 const nlattr &attr,
349 const NestedData &nested_data);
350 AttributeListRefPtr value_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800351
352 private:
353 DISALLOW_COPY_AND_ASSIGN(NetlinkNestedAttribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800354};
355
356class NetlinkRawAttribute : public NetlinkAttribute {
357 public:
358 static const char kMyTypeString[];
359 static const Type kType;
360 NetlinkRawAttribute(int id, const char *id_string)
361 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
362 virtual bool InitFromNlAttr(const nlattr *data);
363 // Gets the value of the data (the header is not stored).
364 virtual bool GetRawValue(ByteString *value) const;
365 // Should set the value of the data (not the attribute header).
366 virtual bool SetRawValue(const ByteString value);
367 virtual bool ToString(std::string *value) const;
368 virtual ByteString Encode() const;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800369
370 private:
371 DISALLOW_COPY_AND_ASSIGN(NetlinkRawAttribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800372};
373
374class NetlinkAttributeGeneric : public NetlinkRawAttribute {
375 public:
376 explicit NetlinkAttributeGeneric(int id);
377 virtual const char *id_string() const;
378
379 private:
380 std::string id_string_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800381
382 DISALLOW_COPY_AND_ASSIGN(NetlinkAttributeGeneric);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800383};
384
385} // namespace shill
386
387#endif // SHILL_NETLINK_ATTRIBUTE_H_