blob: 3dbfa7eb869edeb42a0f562bf9e1d3ea05a14196 [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
12#include <base/memory/weak_ptr.h>
13
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_;
147};
148
149class NetlinkU8Attribute : public NetlinkAttribute {
150 public:
151 static const char kMyTypeString[];
152 static const Type kType;
153 NetlinkU8Attribute(int id, const char *id_string)
154 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
155 virtual bool InitFromNlAttr(const nlattr *data);
156 virtual bool GetU8Value(uint8_t *value) const;
157 virtual bool SetU8Value(uint8_t new_value);
158 virtual bool ToString(std::string *value) const;
159 virtual ByteString Encode() const;
160
161 private:
162 uint8_t value_;
163};
164
165class NetlinkU16Attribute : public NetlinkAttribute {
166 public:
167 static const char kMyTypeString[];
168 static const Type kType;
169 NetlinkU16Attribute(int id, const char *id_string)
170 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
171 virtual bool InitFromNlAttr(const nlattr *data);
172 virtual bool GetU16Value(uint16_t *value) const;
173 virtual bool SetU16Value(uint16_t new_value);
174 virtual bool ToString(std::string *value) const;
175 virtual ByteString Encode() const;
176
177 private:
178 uint16_t value_;
179};
180
181class NetlinkU32Attribute : public NetlinkAttribute {
182 public:
183 static const char kMyTypeString[];
184 static const Type kType;
185 NetlinkU32Attribute(int id, const char *id_string)
186 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
187 virtual bool InitFromNlAttr(const nlattr *data);
188 virtual bool GetU32Value(uint32_t *value) const;
189 virtual bool SetU32Value(uint32_t new_value);
190 virtual bool ToString(std::string *value) const;
191 virtual ByteString Encode() const;
192
193 private:
194 uint32_t value_;
195};
196
197class NetlinkU64Attribute : public NetlinkAttribute {
198 public:
199 static const char kMyTypeString[];
200 static const Type kType;
201 NetlinkU64Attribute(int id, const char *id_string)
202 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
203 virtual bool InitFromNlAttr(const nlattr *data);
204 virtual bool GetU64Value(uint64_t *value) const;
205 virtual bool SetU64Value(uint64_t new_value);
206 virtual bool ToString(std::string *value) const;
207 virtual ByteString Encode() const;
208
209 private:
210 uint64_t value_;
211};
212
213class NetlinkFlagAttribute : public NetlinkAttribute {
214 public:
215 static const char kMyTypeString[];
216 static const Type kType;
217 NetlinkFlagAttribute(int id, const char *id_string)
218 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
219 virtual bool InitFromNlAttr(const nlattr *data);
220 virtual bool GetFlagValue(bool *value) const;
221 virtual bool SetFlagValue(bool new_value);
222 virtual bool ToString(std::string *value) const;
223 virtual ByteString Encode() const;
224
225 private:
226 bool value_;
227};
228
229class NetlinkStringAttribute : public NetlinkAttribute {
230 public:
231 static const char kMyTypeString[];
232 static const Type kType;
233 NetlinkStringAttribute(int id, const char *id_string)
234 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
235 virtual bool InitFromNlAttr(const nlattr *data);
236 virtual bool GetStringValue(std::string *value) const;
237 virtual bool SetStringValue(const std::string new_value);
238 virtual bool ToString(std::string *value) const;
239 virtual ByteString Encode() const;
240
241 private:
242 std::string value_;
243};
244
245class NetlinkNestedAttribute : public NetlinkAttribute {
246 public:
247 static const char kMyTypeString[];
248 static const Type kType;
249 NetlinkNestedAttribute(int id, const char *id_string);
250 virtual bool InitFromNlAttr(const nlattr *data) {
251 LOG(FATAL) << "Try initializing a _specific_ nested type, instead.";
252 return false;
253 }
254 virtual bool GetNestedAttributeList(AttributeListRefPtr *value);
255 virtual bool ConstGetNestedAttributeList(
256 AttributeListConstRefPtr *value) const;
257 virtual bool SetNestedHasAValue();
258 virtual void Print(int log_level, int indent) const;
259 virtual bool ToString(std::string *value) const;
260 virtual ByteString Encode() const;
261
262 protected:
263 // Describes a single nested attribute. Provides the expected values and
264 // type (including further nesting). Normally, an array of these, one for
265 // each attribute at one level of nesting is presented, along with the data
266 // to be parsed, to |InitNestedFromNlAttr|. If the attributes on one level
267 // represent an array, a single |NestedData| is provided and |is_array| is
268 // set (note that one level of nesting either contains _only_ an array or
269 // _no_ array).
270 struct NestedData {
271 nla_policy policy;
272 const char *attribute_name;
273 const NestedData *deeper_nesting;
274 size_t deeper_nesting_size;
275 bool is_array;
276 // TODO(wdg): Add function pointer for a custom attribute parser.
277 };
278
279 // Builds an AttributeList (|list|) that contains all of the attriubtes in
280 // |const_data|. |const_data| should point to the enclosing nested attribute
281 // header; for the example of the nested attribute NL80211_ATTR_CQM:
282 // nlattr::nla_type: NL80211_ATTR_CQM <-- const_data points here
283 // nlattr::nla_len: 12 bytes
284 // nlattr::nla_type: PKT_LOSS_EVENT (1st and only nested attribute)
285 // nlattr::nla_len: 8 bytes
286 // <data>: 0x32
287 // One can assemble (hence, disassemble) a set of child attributes under a
288 // nested attribute parent as an array of elements or as a structure.
289 //
290 // The data is parsed using the expected configuration in |nested_template|.
291 // If the code expects an array, it will pass a single template element and
292 // mark that as an array.
293 static bool InitNestedFromNlAttr(AttributeList *list,
294 const NestedData *nested_template,
295 size_t nested_template_size,
296 const nlattr *const_data);
297
298 static bool ParseNestedArray(AttributeList *list,
299 const NestedData &nested_template,
300 const nlattr *const_data);
301
302 static bool ParseNestedStructure(AttributeList *list,
303 const NestedData *nested_template,
304 size_t nested_template_size,
305 const nlattr *const_data);
306
307 // Helper function used by InitNestedFromNlAttr to add a single child
308 // attribute to a nested attribute.
309 static void AddAttributeToNested(AttributeList *list, uint16_t type, size_t i,
310 const std::string &attribute_name,
311 const nlattr &attr,
312 const NestedData &nested_data);
313 AttributeListRefPtr value_;
314};
315
316class NetlinkRawAttribute : public NetlinkAttribute {
317 public:
318 static const char kMyTypeString[];
319 static const Type kType;
320 NetlinkRawAttribute(int id, const char *id_string)
321 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
322 virtual bool InitFromNlAttr(const nlattr *data);
323 // Gets the value of the data (the header is not stored).
324 virtual bool GetRawValue(ByteString *value) const;
325 // Should set the value of the data (not the attribute header).
326 virtual bool SetRawValue(const ByteString value);
327 virtual bool ToString(std::string *value) const;
328 virtual ByteString Encode() const;
329};
330
331class NetlinkAttributeGeneric : public NetlinkRawAttribute {
332 public:
333 explicit NetlinkAttributeGeneric(int id);
334 virtual const char *id_string() const;
335
336 private:
337 std::string id_string_;
338};
339
340} // namespace shill
341
342#endif // SHILL_NETLINK_ATTRIBUTE_H_