blob: 1c87a8ba7456cf88c2b8a35af02f53c812c5750f [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);
264 virtual bool InitFromNlAttr(const nlattr *data) {
265 LOG(FATAL) << "Try initializing a _specific_ nested type, instead.";
266 return false;
267 }
268 virtual bool GetNestedAttributeList(AttributeListRefPtr *value);
269 virtual bool ConstGetNestedAttributeList(
270 AttributeListConstRefPtr *value) const;
271 virtual bool SetNestedHasAValue();
272 virtual void Print(int log_level, int indent) const;
273 virtual bool ToString(std::string *value) const;
274 virtual ByteString Encode() const;
275
276 protected:
277 // Describes a single nested attribute. Provides the expected values and
278 // type (including further nesting). Normally, an array of these, one for
279 // each attribute at one level of nesting is presented, along with the data
280 // to be parsed, to |InitNestedFromNlAttr|. If the attributes on one level
281 // represent an array, a single |NestedData| is provided and |is_array| is
282 // set (note that one level of nesting either contains _only_ an array or
283 // _no_ array).
284 struct NestedData {
285 nla_policy policy;
286 const char *attribute_name;
287 const NestedData *deeper_nesting;
288 size_t deeper_nesting_size;
289 bool is_array;
290 // TODO(wdg): Add function pointer for a custom attribute parser.
291 };
292
293 // Builds an AttributeList (|list|) that contains all of the attriubtes in
294 // |const_data|. |const_data| should point to the enclosing nested attribute
295 // header; for the example of the nested attribute NL80211_ATTR_CQM:
296 // nlattr::nla_type: NL80211_ATTR_CQM <-- const_data points here
297 // nlattr::nla_len: 12 bytes
298 // nlattr::nla_type: PKT_LOSS_EVENT (1st and only nested attribute)
299 // nlattr::nla_len: 8 bytes
300 // <data>: 0x32
301 // One can assemble (hence, disassemble) a set of child attributes under a
302 // nested attribute parent as an array of elements or as a structure.
303 //
304 // The data is parsed using the expected configuration in |nested_template|.
305 // If the code expects an array, it will pass a single template element and
306 // mark that as an array.
307 static bool InitNestedFromNlAttr(AttributeList *list,
308 const NestedData *nested_template,
309 size_t nested_template_size,
310 const nlattr *const_data);
311
312 static bool ParseNestedArray(AttributeList *list,
313 const NestedData &nested_template,
314 const nlattr *const_data);
315
316 static bool ParseNestedStructure(AttributeList *list,
317 const NestedData *nested_template,
318 size_t nested_template_size,
319 const nlattr *const_data);
320
321 // Helper function used by InitNestedFromNlAttr to add a single child
322 // attribute to a nested attribute.
323 static void AddAttributeToNested(AttributeList *list, uint16_t type, size_t i,
324 const std::string &attribute_name,
325 const nlattr &attr,
326 const NestedData &nested_data);
327 AttributeListRefPtr value_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800328
329 private:
330 DISALLOW_COPY_AND_ASSIGN(NetlinkNestedAttribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800331};
332
333class NetlinkRawAttribute : public NetlinkAttribute {
334 public:
335 static const char kMyTypeString[];
336 static const Type kType;
337 NetlinkRawAttribute(int id, const char *id_string)
338 : NetlinkAttribute(id, id_string, kType, kMyTypeString) {}
339 virtual bool InitFromNlAttr(const nlattr *data);
340 // Gets the value of the data (the header is not stored).
341 virtual bool GetRawValue(ByteString *value) const;
342 // Should set the value of the data (not the attribute header).
343 virtual bool SetRawValue(const ByteString value);
344 virtual bool ToString(std::string *value) const;
345 virtual ByteString Encode() const;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800346
347 private:
348 DISALLOW_COPY_AND_ASSIGN(NetlinkRawAttribute);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800349};
350
351class NetlinkAttributeGeneric : public NetlinkRawAttribute {
352 public:
353 explicit NetlinkAttributeGeneric(int id);
354 virtual const char *id_string() const;
355
356 private:
357 std::string id_string_;
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800358
359 DISALLOW_COPY_AND_ASSIGN(NetlinkAttributeGeneric);
Wade Guthrief162f8b2013-02-27 14:13:55 -0800360};
361
362} // namespace shill
363
364#endif // SHILL_NETLINK_ATTRIBUTE_H_