blob: 33cffd6a5d9d6ac85d8e600937f763fd2aaa324a [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;
252
253 private:
254 std::string value_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800255
256 DISALLOW_COPY_AND_ASSIGN(NetlinkStringAttribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800257};
258
259class NetlinkNestedAttribute : public NetlinkAttribute {
260 public:
261 static const char kMyTypeString[];
262 static const Type kType;
263 NetlinkNestedAttribute(int id, const char *id_string);
Wade Guthrief1b36412013-04-11 14:51:31 -0700264 virtual bool InitFromNlAttr(const nlattr *data);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800265 virtual bool GetNestedAttributeList(AttributeListRefPtr *value);
266 virtual bool ConstGetNestedAttributeList(
267 AttributeListConstRefPtr *value) const;
268 virtual bool SetNestedHasAValue();
269 virtual void Print(int log_level, int indent) const;
270 virtual bool ToString(std::string *value) const;
271 virtual ByteString Encode() const;
272
273 protected:
274 // Describes a single nested attribute. Provides the expected values and
275 // type (including further nesting). Normally, an array of these, one for
276 // each attribute at one level of nesting is presented, along with the data
277 // to be parsed, to |InitNestedFromNlAttr|. If the attributes on one level
278 // represent an array, a single |NestedData| is provided and |is_array| is
279 // set (note that one level of nesting either contains _only_ an array or
280 // _no_ array).
281 struct NestedData {
Wade Guthrief1b36412013-04-11 14:51:31 -0700282 typedef base::Callback<bool (AttributeList *list, size_t id,
283 const std::string &attribute_name,
284 ByteString data)> AttributeParser;
285 typedef std::vector<NestedData> NestedDataVector;
286
287 NestedData();
288 NestedData(uint16_t type, std::string attribute_name, bool is_array);
289 NestedData(uint16_t type, std::string attribute_name, bool is_array,
290 const AttributeParser &parse_attribute);
291 uint16_t type;
292 std::string attribute_name;
293 NestedDataVector deeper_nesting;
Wade Guthrief162f8b2013-02-27 14:13:55 -0800294 bool is_array;
Wade Guthrief1b36412013-04-11 14:51:31 -0700295 // Closure that overrides the usual parsing of this attribute. A non-NULL
296 // value for |parse_attribute| will cause the software to ignore the other
297 // members of the |NestedData| structure.
298 AttributeParser parse_attribute;
Wade Guthrief162f8b2013-02-27 14:13:55 -0800299 };
300
Wade Guthrief1b36412013-04-11 14:51:31 -0700301 NestedData::NestedDataVector nested_template_;
302
Wade Guthrief162f8b2013-02-27 14:13:55 -0800303 // Builds an AttributeList (|list|) that contains all of the attriubtes in
304 // |const_data|. |const_data| should point to the enclosing nested attribute
305 // header; for the example of the nested attribute NL80211_ATTR_CQM:
306 // nlattr::nla_type: NL80211_ATTR_CQM <-- const_data points here
307 // nlattr::nla_len: 12 bytes
308 // nlattr::nla_type: PKT_LOSS_EVENT (1st and only nested attribute)
309 // nlattr::nla_len: 8 bytes
310 // <data>: 0x32
311 // One can assemble (hence, disassemble) a set of child attributes under a
312 // nested attribute parent as an array of elements or as a structure.
313 //
314 // The data is parsed using the expected configuration in |nested_template|.
315 // If the code expects an array, it will pass a single template element and
316 // mark that as an array.
Wade Guthrief1b36412013-04-11 14:51:31 -0700317 static bool InitNestedFromNlAttr(
318 AttributeList *list, const NestedData::NestedDataVector &templates,
319 const nlattr *const_data);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800320
Wade Guthrief1b36412013-04-11 14:51:31 -0700321 static bool ParseNestedArray(
322 AttributeList *list, const NestedData &templates,
323 const nlattr *const_data);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800324
Wade Guthrief1b36412013-04-11 14:51:31 -0700325 static bool ParseNestedStructure(
326 AttributeList *list, const NestedData::NestedDataVector &templates,
327 const nlattr *const_data);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800328
329 // Helper function used by InitNestedFromNlAttr to add a single child
330 // attribute to a nested attribute.
331 static void AddAttributeToNested(AttributeList *list, uint16_t type, size_t i,
332 const std::string &attribute_name,
333 const nlattr &attr,
334 const NestedData &nested_data);
335 AttributeListRefPtr value_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800336
337 private:
338 DISALLOW_COPY_AND_ASSIGN(NetlinkNestedAttribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800339};
340
341class NetlinkRawAttribute : public NetlinkAttribute {
342 public:
343 static const char kMyTypeString[];
344 static const Type kType;
345 NetlinkRawAttribute(int id, const char *id_string)
346 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
347 virtual bool InitFromNlAttr(const nlattr *data);
348 // Gets the value of the data (the header is not stored).
349 virtual bool GetRawValue(ByteString *value) const;
350 // Should set the value of the data (not the attribute header).
351 virtual bool SetRawValue(const ByteString value);
352 virtual bool ToString(std::string *value) const;
353 virtual ByteString Encode() const;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800354
355 private:
356 DISALLOW_COPY_AND_ASSIGN(NetlinkRawAttribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800357};
358
359class NetlinkAttributeGeneric : public NetlinkRawAttribute {
360 public:
361 explicit NetlinkAttributeGeneric(int id);
362 virtual const char *id_string() const;
363
364 private:
365 std::string id_string_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800366
367 DISALLOW_COPY_AND_ASSIGN(NetlinkAttributeGeneric);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800368};
369
370} // namespace shill
371
372#endif // SHILL_NETLINK_ATTRIBUTE_H_