144d362409d5469aed47d19e7908d19bd194493aThomas Graf/*
244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/attr.c		Netlink Attributes
344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
444d362409d5469aed47d19e7908d19bd194493aThomas Graf *	This library is free software; you can redistribute it and/or
544d362409d5469aed47d19e7908d19bd194493aThomas Graf *	modify it under the terms of the GNU Lesser General Public
644d362409d5469aed47d19e7908d19bd194493aThomas Graf *	License as published by the Free Software Foundation version 2.1
744d362409d5469aed47d19e7908d19bd194493aThomas Graf *	of the License.
844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
9dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1144d362409d5469aed47d19e7908d19bd194493aThomas Graf
1244d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-local.h>
1344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h>
1444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h>
1544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/addr.h>
1644d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/attr.h>
1744d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/msg.h>
1844d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <linux/socket.h>
1944d362409d5469aed47d19e7908d19bd194493aThomas Graf
2044d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
2144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @ingroup msg
2244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup attr Attributes
2344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Netlink Attributes Construction/Parsing Interface
24dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
25dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * \section attr_sec Netlink Attributes
26dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Netlink attributes allow for data chunks of arbitary length to be
27dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * attached to a netlink message. Each attribute is encoded with a
28dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * type and length field, both 16 bits, stored in the attribute header
29dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * preceding the attribute data. The main advantage of using attributes
30dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * over packing everything into the family header is that the interface
31dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * stays extendable as new attributes can supersede old attributes while
32dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * remaining backwards compatible. Also attributes can be defined optional
33dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * thus avoiding the transmission of unnecessary empty data blocks.
34dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Special nested attributes allow for more complex data structures to
35dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * be transmitted, e.g. trees, lists, etc.
36dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
37dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * While not required, netlink attributes typically follow the family
38dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * header of a netlink message and must be properly aligned to NLA_ALIGNTO:
39dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code
40dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   +----------------+- - -+---------------+- - -+------------+- - -+
41dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   | Netlink Header | Pad | Family Header | Pad | Attributes | Pad |
42dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   +----------------+- - -+---------------+- - -+------------+- - -+
43dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode
44dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
45dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * The actual attributes are chained together each separately aligned to
46dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * NLA_ALIGNTO. The position of an attribute is defined based on the
47dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * length field of the preceding attributes:
48dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code
49dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   +-------------+- - -+-------------+- - -+------
50dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   | Attribute 1 | Pad | Attribute 2 | Pad | ...
51dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   +-------------+- - -+-------------+- - -+------
52dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   nla_next(attr1)------^
53dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode
54dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
55dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * The attribute itself consists of the attribute header followed by
56dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * the actual payload also aligned to NLA_ALIGNTO. The function nla_data()
57dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * returns a pointer to the start of the payload while nla_len() returns
58dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * the length of the payload in bytes.
59dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
60dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * \b Note: Be aware, NLA_ALIGNTO equals to 4 bytes, therefore it is not
61dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * safe to dereference any 64 bit data types directly.
62dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
6344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code
64dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *    <----------- nla_total_size(payload) ----------->
65dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *    <-------- nla_attr_size(payload) --------->
66dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   +------------------+- - -+- - - - - - - - - +- - -+
67dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   | Attribute Header | Pad |     Payload      | Pad |
68dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   +------------------+- - -+- - - - - - - - - +- - -+
69dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   nla_data(nla)-------------^
70dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *                             <- nla_len(nla) ->
7144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode
7244d362409d5469aed47d19e7908d19bd194493aThomas Graf *
73dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @subsection attr_datatypes Attribute Data Types
74dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * A number of basic data types are supported to simplify access and
75dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * validation of netlink attributes. This data type information is
76dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * not encoded in the attribute, both the kernel and userspace part
77dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * are required to share this information on their own.
78dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
79dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * One of the major advantages of these basic types is the automatic
80dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * validation of each attribute based on an attribute policy. The
81dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * validation covers most of the checks required to safely use
82dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * attributes and thus keeps the individual sanity check to a minimum.
83dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
84dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Never access attribute payload without ensuring basic validation
85dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * first, attributes may:
86dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * - not be present even though required
87dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * - contain less actual payload than expected
88dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * - fake a attribute length which exceeds the end of the message
89dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * - contain unterminated character strings
90dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
91dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Policies are defined as array of the struct nla_policy. The array is
92dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * indexed with the attribute type, therefore the array must be sized
93dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * accordingly.
94dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code
95dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * static struct nla_policy my_policy[ATTR_MAX+1] = {
96dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * 	[ATTR_FOO] = { .type = ..., .minlen = ..., .maxlen = ... },
97dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * };
98dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
99dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * err = nla_validate(attrs, attrlen, ATTR_MAX, &my_policy);
100dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode
101dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
102dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Some basic validations are performed on every attribute, regardless of type.
103dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * - If the attribute type exceeds the maximum attribute type specified or
104dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   the attribute type is lesser-or-equal than zero, the attribute will
105dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   be silently ignored.
106dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * - If the payload length falls below the \a minlen value the attribute
107dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   will be rejected.
108dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * - If \a maxlen is non-zero and the payload length exceeds the \a maxlen
109dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   value the attribute will be rejected.
110dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
111dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
112dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par Unspecific Attribute (NLA_UNSPEC)
113dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * This is the standard type if no type is specified. It is used for
114dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * binary data of arbitary length. Typically this attribute carries
115dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * a binary structure or a stream of bytes.
11644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par
11744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code
118dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // In this example, we will assume a binary structure requires to
119dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // be transmitted. The definition of the structure will typically
120dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // go into a header file available to both the kernel and userspace
121dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // side.
122dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * //
123dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Note: Be careful when putting 64 bit data types into a structure.
124dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // The attribute payload is only aligned to 4 bytes, dereferencing
125dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // the member may fail.
126dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * struct my_struct {
127dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     int a;
128dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     int b;
129dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * };
130dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
131dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // The validation function will not enforce an exact length match to
132dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // allow structures to grow as required. Note: While it is allowed
133dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // to add members to the end of the structure, changing the order or
134dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // inserting members in the middle of the structure will break your
135dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // binary interface.
136dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * static struct nla_policy my_policy[ATTR_MAX+1] = {
137dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     [ATTR_MY_STRICT] = { .type = NLA_UNSPEC,
138dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *                          .minlen = sizeof(struct my_struct) },
139dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
140dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // The binary structure is appened to the message using nla_put()
141dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * struct my_struct foo = { .a = 1, .b = 2 };
142dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_put(msg, ATTR_MY_STRUCT, sizeof(foo), &foo);
143dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
144dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // On the receiving side, a pointer to the structure pointing inside
145dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // the message payload is returned by nla_get().
146dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * if (attrs[ATTR_MY_STRUCT])
147dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     struct my_struct *foo = nla_get(attrs[ATTR_MY_STRUCT]);
14844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode
14944d362409d5469aed47d19e7908d19bd194493aThomas Graf *
150dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par Integers (NLA_U8, NLA_U16, NLA_U32, NLA_U64)
151dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Integers come in different sizes from 8 bit to 64 bit. However, since the
152dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * payload length is aligned to 4 bytes, integers smaller than 32 bit are
153dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * only useful to enforce the maximum range of values.
154dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par
155dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * \b Note: There is no difference made between signed and unsigned integers.
156dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * The validation only enforces the minimal payload length required to store
157dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * an integer of specified type.
158dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par
15944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code
160dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Even though possible, it does not make sense to specify .minlen or
161dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // .maxlen for integer types. The data types implies the corresponding
162dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // minimal payload length.
163dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * static struct nla_policy my_policy[ATTR_MAX+1] = {
164dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     [ATTR_FOO] = { .type = NLA_U32 },
165dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
166dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Numeric values can be appended directly using the respective
167dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // nla_put_uxxx() function
168dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_put_u32(msg, ATTR_FOO, 123);
169dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
170dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Same for the receiving side.
171dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * if (attrs[ATTR_FOO])
172dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     uint32_t foo = nla_get_u32(attrs[ATTR_FOO]);
17344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode
17444d362409d5469aed47d19e7908d19bd194493aThomas Graf *
175dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par Character string (NLA_STRING)
176dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * This data type represents a NUL terminated character string of variable
177dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * length. For binary data streams the type NLA_UNSPEC is recommended.
178dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par
17944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code
180dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Enforce a NUL terminated character string of at most 4 characters
181dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // including the NUL termination.
182dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * static struct nla_policy my_policy[ATTR_MAX+1] = {
183dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     [ATTR_BAR] = { .type = NLA_STRING, maxlen = 4 },
184dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
185dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // nla_put_string() creates a string attribute of the necessary length
186dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // and appends it to the message including the NUL termination.
187dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_put_string(msg, ATTR_BAR, "some text");
188dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
189dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // It is safe to use the returned character string directly if the
190dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // attribute has been validated as the validation enforces the proper
191dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // termination of the string.
192dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * if (attrs[ATTR_BAR])
193dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     char *text = nla_get_string(attrs[ATTR_BAR]);
194dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode
195dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
196dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par Flag (NLA_FLAG)
197dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * This attribute type may be used to indicate the presence of a flag. The
198dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * attribute is only valid if the payload length is zero. The presence of
199dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * the attribute header indicates the presence of the flag.
200dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par
201dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code
202dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // This attribute type is special as .minlen and .maxlen have no effect.
203dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * static struct nla_policy my_policy[ATTR_MAX+1] = {
204dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     [ATTR_FLAG] = { .type = NLA_FLAG },
205dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
206dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // nla_put_flag() appends a zero sized attribute to the message.
207dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_put_flag(msg, ATTR_FLAG);
208dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
209dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // There is no need for a receival function, the presence is the value.
210dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * if (attrs[ATTR_FLAG])
211dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     // flag is present
212dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode
213dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
214dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par Micro Seconds (NLA_MSECS)
215dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
216dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par Nested Attribute (NLA_NESTED)
217dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Attributes can be nested and put into a container to create groups, lists
218dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * or to construct trees of attributes. Nested attributes are often used to
219dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * pass attributes to a subsystem where the top layer has no knowledge of the
220dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * configuration possibilities of each subsystem.
221dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par
222dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * \b Note: When validating the attributes using nlmsg_validate() or
223dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nlmsg_parse() it will only affect the top level attributes. Each
224dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * level of nested attributes must be validated seperately using
225dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_parse_nested() or nla_validate().
226dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par
227dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code
228dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // The minimal length policy may be used to enforce the presence of at
229dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // least one attribute.
230dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * static struct nla_policy my_policy[ATTR_MAX+1] = {
231dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     [ATTR_OPTS] = { .type = NLA_NESTED, minlen = NLA_HDRLEN },
232dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
233dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Nested attributes are constructed by enclosing the attributes
234dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // to be nested with calls to nla_nest_start() respetively nla_nest_end().
235dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * struct nlattr *opts = nla_nest_start(msg, ATTR_OPTS);
236dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_put_u32(msg, ATTR_FOO, 123);
237dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_put_string(msg, ATTR_BAR, "some text");
238dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_nest_end(msg, opts);
239dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
240dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // Various methods exist to parse nested attributes, the easiest being
241dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // nla_parse_nested() which also allows validation in the same step.
242dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * if (attrs[ATTR_OPTS]) {
243dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     struct nlattr *nested[ATTR_MAX+1];
244dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
245dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     nla_parse_nested(nested, ATTR_MAX, attrs[ATTR_OPTS], &policy);
246dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
247dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     if (nested[ATTR_FOO])
248dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *         uint32_t foo = nla_get_u32(nested[ATTR_FOO]);
249dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * }
250dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode
251dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
252dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @subsection attr_exceptions Exception Based Attribute Construction
253dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Often a large number of attributes are added to a message in a single
254dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * function. In order to simplify error handling, a second set of
255dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * construction functions exist which jump to a error label when they
256dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * fail instead of returning an error code. This second set consists
257dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * of macros which are named after their error code based counterpart
258dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * except that the name is written all uppercase.
259dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
260dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * All of the macros jump to the target \c nla_put_failure if they fail.
261dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code
262dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * void my_func(struct nl_msg *msg)
263dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * {
264dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     NLA_PUT_U32(msg, ATTR_FOO, 10);
265dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     NLA_PUT_STRING(msg, ATTR_BAR, "bar");
266dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
267dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     return 0;
268dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
269dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_put_failure:
2708a3efffa5b3fde252675239914118664d36a2c24Thomas Graf *     return -NLE_NOMEM;
271dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * }
272dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode
273dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
274dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @subsection attr_examples Examples
275dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par Example 1.1 Constructing a netlink message with attributes.
276dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code
277dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * struct nl_msg *build_msg(int ifindex, struct nl_addr *lladdr, int mtu)
27844d362409d5469aed47d19e7908d19bd194493aThomas Graf * {
279dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     struct nl_msg *msg;
280dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     struct nlattr *info, *vlan;
281dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     struct ifinfomsg ifi = {
282dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *         .ifi_family = AF_INET,
283dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *         .ifi_index = ifindex,
284dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     };
285dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
286dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     // Allocate a new netlink message, type=RTM_SETLINK, flags=NLM_F_ECHO
287dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     if (!(msg = nlmsg_alloc_simple(RTM_SETLINK, NLM_F_ECHO)))
288dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *         return NULL;
289dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
290dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     // Append the family specific header (struct ifinfomsg)
291dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0)
292dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *         goto nla_put_failure
293dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
294dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     // Append a 32 bit integer attribute to carry the MTU
295dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     NLA_PUT_U32(msg, IFLA_MTU, mtu);
296dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
297dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     // Append a unspecific attribute to carry the link layer address
298dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     NLA_PUT_ADDR(msg, IFLA_ADDRESS, lladdr);
299dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
300dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     // Append a container for nested attributes to carry link information
301dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     if (!(info = nla_nest_start(msg, IFLA_LINKINFO)))
302dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *         goto nla_put_failure;
303dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
304dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     // Put a string attribute into the container
305dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     NLA_PUT_STRING(msg, IFLA_INFO_KIND, "vlan");
306dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
307dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     // Append another container inside the open container to carry
308dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     // vlan specific attributes
309dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     if (!(vlan = nla_nest_start(msg, IFLA_INFO_DATA)))
310dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *         goto nla_put_failure;
311dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
312dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     // add vlan specific info attributes here...
313dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
314dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     // Finish nesting the vlan attributes and close the second container.
315dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     nla_nest_end(msg, vlan);
316dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
317dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     // Finish nesting the link info attribute and close the first container.
318dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     nla_nest_end(msg, info);
319dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
320dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     return msg;
321dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
322dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * // If any of the construction macros fails, we end up here.
323dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_put_failure:
324dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     nlmsg_free(msg);
325dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     return NULL;
32644d362409d5469aed47d19e7908d19bd194493aThomas Graf * }
327dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode
328dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
329dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @par Example 2.1 Parsing a netlink message with attributes.
330dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code
331dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * int parse_message(struct nl_msg *msg)
332dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * {
333dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     // The policy defines two attributes: a 32 bit integer and a container
334dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     // for nested attributes.
335dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     struct nla_policy attr_policy[ATTR_MAX+1] = {
336dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *         [ATTR_FOO] = { .type = NLA_U32 },
337dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *         [ATTR_BAR] = { .type = NLA_NESTED },
338dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     };
339dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     struct nlattr *attrs[ATTR_MAX+1];
340dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     int err;
341dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
342dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     // The nlmsg_parse() function will make sure that the message contains
343dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     // enough payload to hold the header (struct my_hdr), validates any
344dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     // attributes attached to the messages and stores a pointer to each
345dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     // attribute in the attrs[] array accessable by attribute type.
346dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     if ((err = nlmsg_parse(nlmsg_hdr(msg), sizeof(struct my_hdr), attrs,
347dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *                            ATTR_MAX, attr_policy)) < 0)
348dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *         goto errout;
34944d362409d5469aed47d19e7908d19bd194493aThomas Graf *
350dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     if (attrs[ATTR_FOO]) {
351dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *         // It is safe to directly access the attribute payload without
352dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *         // any further checks since nlmsg_parse() enforced the policy.
353dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *         uint32_t foo = nla_get_u32(attrs[ATTR_FOO]);
354dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     }
35544d362409d5469aed47d19e7908d19bd194493aThomas Graf *
356dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     if (attrs[ATTR_BAR]) {
357dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *         struct nlattr *nested[NESTED_MAX+1];
358dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
359dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *         // Attributes nested in a container can be parsed the same way
360dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *         // as top level attributes.
361dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *         if ((err = nla_parse_nested(nested, NESTED_MAX, attrs[ATTR_BAR],
362dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *                                     nested_policy)) < 0)
363dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *             goto errout;
364dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
365dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *         // Process nested attributes here.
366dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     }
367dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
368dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     err = 0;
369dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * errout:
370dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *     return err;
371dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * }
37244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode
373dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
37444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
37544d362409d5469aed47d19e7908d19bd194493aThomas Graf */
37644d362409d5469aed47d19e7908d19bd194493aThomas Graf
37744d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
378dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @name Attribute Size Calculation
37944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
38044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
38144d362409d5469aed47d19e7908d19bd194493aThomas Graf
38244d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
383dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return size of attribute whithout padding.
384dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg payload		Payload length of attribute.
385dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
386dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code
387dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *    <-------- nla_attr_size(payload) --------->
388dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   +------------------+- - -+- - - - - - - - - +- - -+
389dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   | Attribute Header | Pad |     Payload      | Pad |
390dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   +------------------+- - -+- - - - - - - - - +- - -+
391dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode
392dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
393dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Size of attribute in bytes without padding.
39444d362409d5469aed47d19e7908d19bd194493aThomas Graf */
39544d362409d5469aed47d19e7908d19bd194493aThomas Grafint nla_attr_size(int payload)
39644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
39744d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NLA_HDRLEN + payload;
39844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
39944d362409d5469aed47d19e7908d19bd194493aThomas Graf
40044d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
401dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return size of attribute including padding.
402dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg payload		Payload length of attribute.
403dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
404dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code
405dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *    <----------- nla_total_size(payload) ----------->
406dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   +------------------+- - -+- - - - - - - - - +- - -+
407dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   | Attribute Header | Pad |     Payload      | Pad |
408dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   +------------------+- - -+- - - - - - - - - +- - -+
409dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode
410dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
411dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Size of attribute in bytes.
41244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
41344d362409d5469aed47d19e7908d19bd194493aThomas Grafint nla_total_size(int payload)
41444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
41544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NLA_ALIGN(nla_attr_size(payload));
41644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
41744d362409d5469aed47d19e7908d19bd194493aThomas Graf
41844d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
419dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return length of padding at the tail of the attribute.
420dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg payload		Payload length of attribute.
421dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
422dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @code
423dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   +------------------+- - -+- - - - - - - - - +- - -+
424dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   | Attribute Header | Pad |     Payload      | Pad |
425dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *   +------------------+- - -+- - - - - - - - - +- - -+
426dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *                                                <--->
427dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @endcode
428dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
429dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Length of padding in bytes.
43044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
43144d362409d5469aed47d19e7908d19bd194493aThomas Grafint nla_padlen(int payload)
43244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
43344d362409d5469aed47d19e7908d19bd194493aThomas Graf	return nla_total_size(payload) - nla_attr_size(payload);
43444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
43544d362409d5469aed47d19e7908d19bd194493aThomas Graf
43644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
43744d362409d5469aed47d19e7908d19bd194493aThomas Graf
43844d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
439dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @name Parsing Attributes
44044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
44144d362409d5469aed47d19e7908d19bd194493aThomas Graf */
44244d362409d5469aed47d19e7908d19bd194493aThomas Graf
44344d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
444dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return type of the attribute.
445dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla		Attribute.
446dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
447dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Type of attribute.
44844d362409d5469aed47d19e7908d19bd194493aThomas Graf */
44944d362409d5469aed47d19e7908d19bd194493aThomas Grafint nla_type(const struct nlattr *nla)
45044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
45144d362409d5469aed47d19e7908d19bd194493aThomas Graf	return nla->nla_type & NLA_TYPE_MASK;
45244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
45344d362409d5469aed47d19e7908d19bd194493aThomas Graf
45444d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
455dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return pointer to the payload section.
456dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla		Attribute.
457dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
458dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Pointer to start of payload section.
45944d362409d5469aed47d19e7908d19bd194493aThomas Graf */
46044d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid *nla_data(const struct nlattr *nla)
46144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
46244d362409d5469aed47d19e7908d19bd194493aThomas Graf	return (char *) nla + NLA_HDRLEN;
46344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
46444d362409d5469aed47d19e7908d19bd194493aThomas Graf
46544d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
466dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return length of the payload .
467dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla		Attribute
468dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
469dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Length of payload in bytes.
47044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
47144d362409d5469aed47d19e7908d19bd194493aThomas Grafint nla_len(const struct nlattr *nla)
47244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
47344d362409d5469aed47d19e7908d19bd194493aThomas Graf	return nla->nla_len - NLA_HDRLEN;
47444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
47544d362409d5469aed47d19e7908d19bd194493aThomas Graf
47644d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
477dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Check if the attribute header and payload can be accessed safely.
478dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla		Attribute of any kind.
479dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg remaining	Number of bytes remaining in attribute stream.
480dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
481dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Verifies that the header and payload do not exceed the number of
482dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * bytes left in the attribute stream. This function must be called
483dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * before access the attribute header or payload when iterating over
484dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * the attribute stream using nla_next().
485dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
486dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return True if the attribute can be accessed safely, false otherwise.
48744d362409d5469aed47d19e7908d19bd194493aThomas Graf */
48844d362409d5469aed47d19e7908d19bd194493aThomas Grafint nla_ok(const struct nlattr *nla, int remaining)
48944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
49044d362409d5469aed47d19e7908d19bd194493aThomas Graf	return remaining >= sizeof(*nla) &&
49144d362409d5469aed47d19e7908d19bd194493aThomas Graf	       nla->nla_len >= sizeof(*nla) &&
49244d362409d5469aed47d19e7908d19bd194493aThomas Graf	       nla->nla_len <= remaining;
49344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
49444d362409d5469aed47d19e7908d19bd194493aThomas Graf
49544d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
496dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return next attribute in a stream of attributes.
497dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla		Attribute of any kind.
498dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg remaining	Variable to count remaining bytes in stream.
499dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
500dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Calculates the offset to the next attribute based on the attribute
501dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * given. The attribute provided is assumed to be accessible, the
502dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * caller is responsible to use nla_ok() beforehand. The offset (length
503dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * of specified attribute including padding) is then subtracted from
504dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * the remaining bytes variable and a pointer to the next attribute is
505dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * returned.
506dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
507dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * nla_next() can be called as long as remainig is >0.
50844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
509dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Pointer to next attribute.
51044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
51144d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nlattr *nla_next(const struct nlattr *nla, int *remaining)
51244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
51344d362409d5469aed47d19e7908d19bd194493aThomas Graf	int totlen = NLA_ALIGN(nla->nla_len);
51444d362409d5469aed47d19e7908d19bd194493aThomas Graf
51544d362409d5469aed47d19e7908d19bd194493aThomas Graf	*remaining -= totlen;
51644d362409d5469aed47d19e7908d19bd194493aThomas Graf	return (struct nlattr *) ((char *) nla + totlen);
51744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
51844d362409d5469aed47d19e7908d19bd194493aThomas Graf
51944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = {
52044d362409d5469aed47d19e7908d19bd194493aThomas Graf	[NLA_U8]	= sizeof(uint8_t),
52144d362409d5469aed47d19e7908d19bd194493aThomas Graf	[NLA_U16]	= sizeof(uint16_t),
52244d362409d5469aed47d19e7908d19bd194493aThomas Graf	[NLA_U32]	= sizeof(uint32_t),
52344d362409d5469aed47d19e7908d19bd194493aThomas Graf	[NLA_U64]	= sizeof(uint64_t),
52444d362409d5469aed47d19e7908d19bd194493aThomas Graf	[NLA_STRING]	= 1,
52544d362409d5469aed47d19e7908d19bd194493aThomas Graf};
52644d362409d5469aed47d19e7908d19bd194493aThomas Graf
52744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int validate_nla(struct nlattr *nla, int maxtype,
52844d362409d5469aed47d19e7908d19bd194493aThomas Graf			struct nla_policy *policy)
52944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
53044d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nla_policy *pt;
53144d362409d5469aed47d19e7908d19bd194493aThomas Graf	int minlen = 0, type = nla_type(nla);
53244d362409d5469aed47d19e7908d19bd194493aThomas Graf
53344d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (type <= 0 || type > maxtype)
53444d362409d5469aed47d19e7908d19bd194493aThomas Graf		return 0;
53544d362409d5469aed47d19e7908d19bd194493aThomas Graf
53644d362409d5469aed47d19e7908d19bd194493aThomas Graf	pt = &policy[type];
53744d362409d5469aed47d19e7908d19bd194493aThomas Graf
53844d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (pt->type > NLA_TYPE_MAX)
53944d362409d5469aed47d19e7908d19bd194493aThomas Graf		BUG();
54044d362409d5469aed47d19e7908d19bd194493aThomas Graf
54144d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (pt->minlen)
54244d362409d5469aed47d19e7908d19bd194493aThomas Graf		minlen = pt->minlen;
54344d362409d5469aed47d19e7908d19bd194493aThomas Graf	else if (pt->type != NLA_UNSPEC)
54444d362409d5469aed47d19e7908d19bd194493aThomas Graf		minlen = nla_attr_minlen[pt->type];
54544d362409d5469aed47d19e7908d19bd194493aThomas Graf
54644d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (pt->type == NLA_FLAG && nla_len(nla) > 0)
5478a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -NLE_RANGE;
54844d362409d5469aed47d19e7908d19bd194493aThomas Graf
54944d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (nla_len(nla) < minlen)
5508a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -NLE_RANGE;
55144d362409d5469aed47d19e7908d19bd194493aThomas Graf
55244d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (pt->maxlen && nla_len(nla) > pt->maxlen)
5538a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -NLE_RANGE;
55444d362409d5469aed47d19e7908d19bd194493aThomas Graf
55544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (pt->type == NLA_STRING) {
55644d362409d5469aed47d19e7908d19bd194493aThomas Graf		char *data = nla_data(nla);
55744d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (data[nla_len(nla) - 1] != '\0')
5588a3efffa5b3fde252675239914118664d36a2c24Thomas Graf			return -NLE_INVAL;
55944d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
56044d362409d5469aed47d19e7908d19bd194493aThomas Graf
56144d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
56244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
56344d362409d5469aed47d19e7908d19bd194493aThomas Graf
56444d362409d5469aed47d19e7908d19bd194493aThomas Graf
56544d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
566dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Create attribute index based on a stream of attributes.
567dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg tb		Index array to be filled (maxtype+1 elements).
568dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg maxtype		Maximum attribute type expected and accepted.
569dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg head		Head of attribute stream.
570dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg len		Length of attribute stream.
571dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg policy		Attribute validation policy.
57244d362409d5469aed47d19e7908d19bd194493aThomas Graf *
573dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Iterates over the stream of attributes and stores a pointer to each
574dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * attribute in the index array using the attribute type as index to
575dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * the array. Attribute with a type greater than the maximum type
576dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * specified will be silently ignored in order to maintain backwards
577dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * compatibility. If \a policy is not NULL, the attribute will be
578dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * validated using the specified policy.
57944d362409d5469aed47d19e7908d19bd194493aThomas Graf *
580dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_validate
58144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code.
58244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
58344d362409d5469aed47d19e7908d19bd194493aThomas Grafint nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
58444d362409d5469aed47d19e7908d19bd194493aThomas Graf	      struct nla_policy *policy)
58544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
58644d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nlattr *nla;
58744d362409d5469aed47d19e7908d19bd194493aThomas Graf	int rem, err;
58844d362409d5469aed47d19e7908d19bd194493aThomas Graf
58944d362409d5469aed47d19e7908d19bd194493aThomas Graf	memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
59044d362409d5469aed47d19e7908d19bd194493aThomas Graf
59144d362409d5469aed47d19e7908d19bd194493aThomas Graf	nla_for_each_attr(nla, head, len, rem) {
59244d362409d5469aed47d19e7908d19bd194493aThomas Graf		int type = nla_type(nla);
59344d362409d5469aed47d19e7908d19bd194493aThomas Graf
59444d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (type == 0) {
59544d362409d5469aed47d19e7908d19bd194493aThomas Graf			fprintf(stderr, "Illegal nla->nla_type == 0\n");
59644d362409d5469aed47d19e7908d19bd194493aThomas Graf			continue;
59744d362409d5469aed47d19e7908d19bd194493aThomas Graf		}
59844d362409d5469aed47d19e7908d19bd194493aThomas Graf
59944d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (type <= maxtype) {
60044d362409d5469aed47d19e7908d19bd194493aThomas Graf			if (policy) {
60144d362409d5469aed47d19e7908d19bd194493aThomas Graf				err = validate_nla(nla, maxtype, policy);
60244d362409d5469aed47d19e7908d19bd194493aThomas Graf				if (err < 0)
60344d362409d5469aed47d19e7908d19bd194493aThomas Graf					goto errout;
60444d362409d5469aed47d19e7908d19bd194493aThomas Graf			}
60544d362409d5469aed47d19e7908d19bd194493aThomas Graf
60644d362409d5469aed47d19e7908d19bd194493aThomas Graf			tb[type] = nla;
60744d362409d5469aed47d19e7908d19bd194493aThomas Graf		}
60844d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
60944d362409d5469aed47d19e7908d19bd194493aThomas Graf
61044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (rem > 0)
61144d362409d5469aed47d19e7908d19bd194493aThomas Graf		fprintf(stderr, "netlink: %d bytes leftover after parsing "
61244d362409d5469aed47d19e7908d19bd194493aThomas Graf		       "attributes.\n", rem);
61344d362409d5469aed47d19e7908d19bd194493aThomas Graf
61444d362409d5469aed47d19e7908d19bd194493aThomas Graf	err = 0;
61544d362409d5469aed47d19e7908d19bd194493aThomas Graferrout:
61644d362409d5469aed47d19e7908d19bd194493aThomas Graf	return err;
61744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
61844d362409d5469aed47d19e7908d19bd194493aThomas Graf
61944d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
620dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Validate a stream of attributes.
621dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg head		Head of attributes stream.
622dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg len		Length of attributes stream.
623dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg maxtype		Maximum attribute type expected and accepted.
624dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg policy		Validation policy.
62544d362409d5469aed47d19e7908d19bd194493aThomas Graf *
626dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Iterates over the stream of attributes and validates each attribute
627dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * one by one using the specified policy. Attributes with a type greater
628dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * than the maximum type specified will be silently ignored in order to
629dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * maintain backwards compatibility.
63044d362409d5469aed47d19e7908d19bd194493aThomas Graf *
631dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * See \ref attr_datatypes for more details on what kind of validation
632dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * checks are performed on each attribute data type.
63344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
63444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code.
63544d362409d5469aed47d19e7908d19bd194493aThomas Graf */
63644d362409d5469aed47d19e7908d19bd194493aThomas Grafint nla_validate(struct nlattr *head, int len, int maxtype,
63744d362409d5469aed47d19e7908d19bd194493aThomas Graf		 struct nla_policy *policy)
63844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
63944d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nlattr *nla;
64044d362409d5469aed47d19e7908d19bd194493aThomas Graf	int rem, err;
64144d362409d5469aed47d19e7908d19bd194493aThomas Graf
64244d362409d5469aed47d19e7908d19bd194493aThomas Graf	nla_for_each_attr(nla, head, len, rem) {
64344d362409d5469aed47d19e7908d19bd194493aThomas Graf		err = validate_nla(nla, maxtype, policy);
64444d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (err < 0)
64544d362409d5469aed47d19e7908d19bd194493aThomas Graf			goto errout;
64644d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
64744d362409d5469aed47d19e7908d19bd194493aThomas Graf
64844d362409d5469aed47d19e7908d19bd194493aThomas Graf	err = 0;
64944d362409d5469aed47d19e7908d19bd194493aThomas Graferrout:
65044d362409d5469aed47d19e7908d19bd194493aThomas Graf	return err;
65144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
65244d362409d5469aed47d19e7908d19bd194493aThomas Graf
65344d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
654dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Find a single attribute in a stream of attributes.
655dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg head		Head of attributes stream.
656dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg len		Length of attributes stream.
657dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype	Attribute type to look for.
65844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
659dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Iterates over the stream of attributes and compares each type with
660dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * the type specified. Returns the first attribute which matches the
661dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * type.
662dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
663dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Pointer to attribute found or NULL.
66444d362409d5469aed47d19e7908d19bd194493aThomas Graf */
66544d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nlattr *nla_find(struct nlattr *head, int len, int attrtype)
66644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
66744d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nlattr *nla;
66844d362409d5469aed47d19e7908d19bd194493aThomas Graf	int rem;
66944d362409d5469aed47d19e7908d19bd194493aThomas Graf
67044d362409d5469aed47d19e7908d19bd194493aThomas Graf	nla_for_each_attr(nla, head, len, rem)
67144d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (nla_type(nla) == attrtype)
67244d362409d5469aed47d19e7908d19bd194493aThomas Graf			return nla;
67344d362409d5469aed47d19e7908d19bd194493aThomas Graf
67444d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NULL;
67544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
67644d362409d5469aed47d19e7908d19bd194493aThomas Graf
67744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
67844d362409d5469aed47d19e7908d19bd194493aThomas Graf
67944d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
680dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @name Helper Functions
68144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
68244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
68344d362409d5469aed47d19e7908d19bd194493aThomas Graf
68444d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
685dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Copy attribute payload to another memory area.
686dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg dest		Pointer to destination memory area.
687dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg src		Attribute
688dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg count		Number of bytes to copy at most.
68944d362409d5469aed47d19e7908d19bd194493aThomas Graf *
69044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Note: The number of bytes copied is limited by the length of
691dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *       the attribute payload.
69244d362409d5469aed47d19e7908d19bd194493aThomas Graf *
693dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return The number of bytes copied to dest.
69444d362409d5469aed47d19e7908d19bd194493aThomas Graf */
69544d362409d5469aed47d19e7908d19bd194493aThomas Grafint nla_memcpy(void *dest, struct nlattr *src, int count)
69644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
69744d362409d5469aed47d19e7908d19bd194493aThomas Graf	int minlen;
69844d362409d5469aed47d19e7908d19bd194493aThomas Graf
69944d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (!src)
70044d362409d5469aed47d19e7908d19bd194493aThomas Graf		return 0;
70144d362409d5469aed47d19e7908d19bd194493aThomas Graf
70244d362409d5469aed47d19e7908d19bd194493aThomas Graf	minlen = min_t(int, count, nla_len(src));
70344d362409d5469aed47d19e7908d19bd194493aThomas Graf	memcpy(dest, nla_data(src), minlen);
70444d362409d5469aed47d19e7908d19bd194493aThomas Graf
70544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return minlen;
70644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
70744d362409d5469aed47d19e7908d19bd194493aThomas Graf
70844d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
709dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Copy string attribute payload to a buffer.
710dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg dst		Pointer to destination buffer.
711dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla		Attribute of type NLA_STRING.
712dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg dstsize		Size of destination buffer in bytes.
71344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
714dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Copies at most dstsize - 1 bytes to the destination buffer.
715dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * The result is always a valid NUL terminated string. Unlike
71644d362409d5469aed47d19e7908d19bd194493aThomas Graf * strlcpy the destination buffer is always padded out.
71744d362409d5469aed47d19e7908d19bd194493aThomas Graf *
718dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return The length of string attribute without the terminating NUL.
71944d362409d5469aed47d19e7908d19bd194493aThomas Graf */
72044d362409d5469aed47d19e7908d19bd194493aThomas Grafsize_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
72144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
72244d362409d5469aed47d19e7908d19bd194493aThomas Graf	size_t srclen = nla_len(nla);
72344d362409d5469aed47d19e7908d19bd194493aThomas Graf	char *src = nla_data(nla);
72444d362409d5469aed47d19e7908d19bd194493aThomas Graf
72544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (srclen > 0 && src[srclen - 1] == '\0')
72644d362409d5469aed47d19e7908d19bd194493aThomas Graf		srclen--;
72744d362409d5469aed47d19e7908d19bd194493aThomas Graf
72844d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (dstsize > 0) {
72944d362409d5469aed47d19e7908d19bd194493aThomas Graf		size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
73044d362409d5469aed47d19e7908d19bd194493aThomas Graf
73144d362409d5469aed47d19e7908d19bd194493aThomas Graf		memset(dst, 0, dstsize);
73244d362409d5469aed47d19e7908d19bd194493aThomas Graf		memcpy(dst, src, len);
73344d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
73444d362409d5469aed47d19e7908d19bd194493aThomas Graf
73544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return srclen;
73644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
73744d362409d5469aed47d19e7908d19bd194493aThomas Graf
73844d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
739dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Compare attribute payload with memory area.
740dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla		Attribute.
741dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg data		Memory area to compare to.
742dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg size		Number of bytes to compare.
743dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
744dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see memcmp(3)
745dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return An integer less than, equal to, or greater than zero.
74644d362409d5469aed47d19e7908d19bd194493aThomas Graf */
747dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_memcmp(const struct nlattr *nla, const void *data, size_t size)
74844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
74944d362409d5469aed47d19e7908d19bd194493aThomas Graf	int d = nla_len(nla) - size;
75044d362409d5469aed47d19e7908d19bd194493aThomas Graf
75144d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (d == 0)
75244d362409d5469aed47d19e7908d19bd194493aThomas Graf		d = memcmp(nla_data(nla), data, size);
75344d362409d5469aed47d19e7908d19bd194493aThomas Graf
75444d362409d5469aed47d19e7908d19bd194493aThomas Graf	return d;
75544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
75644d362409d5469aed47d19e7908d19bd194493aThomas Graf
75744d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
758dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Compare string attribute payload with string
759dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla		Attribute of type NLA_STRING.
760dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg str		NUL terminated string.
761dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
762dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see strcmp(3)
763dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return An integer less than, equal to, or greater than zero.
76444d362409d5469aed47d19e7908d19bd194493aThomas Graf */
76544d362409d5469aed47d19e7908d19bd194493aThomas Grafint nla_strcmp(const struct nlattr *nla, const char *str)
76644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
76744d362409d5469aed47d19e7908d19bd194493aThomas Graf	int len = strlen(str) + 1;
76844d362409d5469aed47d19e7908d19bd194493aThomas Graf	int d = nla_len(nla) - len;
76944d362409d5469aed47d19e7908d19bd194493aThomas Graf
77044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (d == 0)
77144d362409d5469aed47d19e7908d19bd194493aThomas Graf		d = memcmp(nla_data(nla), str, len);
77244d362409d5469aed47d19e7908d19bd194493aThomas Graf
77344d362409d5469aed47d19e7908d19bd194493aThomas Graf	return d;
77444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
77544d362409d5469aed47d19e7908d19bd194493aThomas Graf
77644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
77744d362409d5469aed47d19e7908d19bd194493aThomas Graf
77844d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
779dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @name Unspecific Attribute
78044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
78144d362409d5469aed47d19e7908d19bd194493aThomas Graf */
78244d362409d5469aed47d19e7908d19bd194493aThomas Graf
78344d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
784dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Reserve space for a attribute.
785dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg		Netlink Message.
786dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype	Attribute Type.
787dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrlen		Length of payload.
788dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
789dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Reserves room for a attribute in the specified netlink message and
790dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * fills in the attribute header (type, length). Returns NULL if there
791dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * is unsuficient space for the attribute.
79244d362409d5469aed47d19e7908d19bd194493aThomas Graf *
793dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Any padding between payload and the start of the next attribute is
794dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * zeroed out.
795dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
796dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Pointer to start of attribute or NULL on failure.
79744d362409d5469aed47d19e7908d19bd194493aThomas Graf */
798dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafstruct nlattr *nla_reserve(struct nl_msg *msg, int attrtype, int attrlen)
79944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
80044d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nlattr *nla;
80144d362409d5469aed47d19e7908d19bd194493aThomas Graf	int tlen;
80244d362409d5469aed47d19e7908d19bd194493aThomas Graf
803dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	tlen = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) + nla_total_size(attrlen);
80444d362409d5469aed47d19e7908d19bd194493aThomas Graf
8058a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	if ((tlen + msg->nm_nlh->nlmsg_len) > msg->nm_size)
80644d362409d5469aed47d19e7908d19bd194493aThomas Graf		return NULL;
80744d362409d5469aed47d19e7908d19bd194493aThomas Graf
808dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	nla = (struct nlattr *) nlmsg_tail(msg->nm_nlh);
80944d362409d5469aed47d19e7908d19bd194493aThomas Graf	nla->nla_type = attrtype;
81044d362409d5469aed47d19e7908d19bd194493aThomas Graf	nla->nla_len = nla_attr_size(attrlen);
81144d362409d5469aed47d19e7908d19bd194493aThomas Graf
81244d362409d5469aed47d19e7908d19bd194493aThomas Graf	memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen));
813dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	msg->nm_nlh->nlmsg_len = tlen;
81444d362409d5469aed47d19e7908d19bd194493aThomas Graf
815936c9844b0ff4aab06301f18fe31e08b1818d0a2Patrick McHardy	NL_DBG(2, "msg %p: Reserved %d bytes at offset +%td for attr %d "
816dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf		  "nlmsg_len=%d\n", msg, attrlen,
817dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf		  (void *) nla - nlmsg_data(msg->nm_nlh),
818dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf		  attrtype, msg->nm_nlh->nlmsg_len);
81944d362409d5469aed47d19e7908d19bd194493aThomas Graf
82044d362409d5469aed47d19e7908d19bd194493aThomas Graf	return nla;
82144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
82244d362409d5469aed47d19e7908d19bd194493aThomas Graf
82344d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
824dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add a unspecific attribute to netlink message.
825dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg		Netlink message.
826dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype	Attribute type.
827dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg datalen		Length of data to be used as payload.
828dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg data		Pointer to data to be used as attribute payload.
829dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
830dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Reserves room for a unspecific attribute and copies the provided data
831dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * into the message as payload of the attribute. Returns an error if there
832dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * is insufficient space for the attribute.
83344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
834dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_reserve
835dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code.
83644d362409d5469aed47d19e7908d19bd194493aThomas Graf */
837dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data)
83844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
83944d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nlattr *nla;
84044d362409d5469aed47d19e7908d19bd194493aThomas Graf
841dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	nla = nla_reserve(msg, attrtype, datalen);
84244d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (!nla)
8438a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -NLE_NOMEM;
84444d362409d5469aed47d19e7908d19bd194493aThomas Graf
845dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	memcpy(nla_data(nla), data, datalen);
846936c9844b0ff4aab06301f18fe31e08b1818d0a2Patrick McHardy	NL_DBG(2, "msg %p: Wrote %d bytes at offset +%td for attr %d\n",
847dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	       msg, datalen, (void *) nla - nlmsg_data(msg->nm_nlh), attrtype);
84844d362409d5469aed47d19e7908d19bd194493aThomas Graf
84944d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
85044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
85144d362409d5469aed47d19e7908d19bd194493aThomas Graf
85244d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
853dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add abstract data as unspecific attribute to netlink message.
854dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg		Netlink message.
855dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype	Attribute type.
856dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg data		Abstract data object.
85744d362409d5469aed47d19e7908d19bd194493aThomas Graf *
858dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Equivalent to nla_put() except that the length of the payload is
859dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * derived from the abstract data object.
860dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
861dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_put
862dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code.
86344d362409d5469aed47d19e7908d19bd194493aThomas Graf */
864dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put_data(struct nl_msg *msg, int attrtype, struct nl_data *data)
86544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
866dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	return nla_put(msg, attrtype, nl_data_get_size(data),
867dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf		       nl_data_get(data));
868dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf}
869dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf
87044d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
871dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add abstract address as unspecific attribute to netlink message.
872dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg		Netlink message.
873dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype	Attribute type.
874dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg addr		Abstract address object.
875dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
876dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_put
877dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code.
87844d362409d5469aed47d19e7908d19bd194493aThomas Graf */
879dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put_addr(struct nl_msg *msg, int attrtype, struct nl_addr *addr)
880dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf{
881dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	return nla_put(msg, attrtype, nl_addr_get_len(addr),
882dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf		       nl_addr_get_binary_addr(addr));
883dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf}
884dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf
885dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf/** @} */
886dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf
88744d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
888dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @name Integer Attributes
889dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf */
890dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf
891dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf/**
892dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add 8 bit integer attribute to netlink message.
893dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg		Netlink message.
894dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype	Attribute type.
895dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg value		Numeric value to store as payload.
896dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
897dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_put
898dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code.
89944d362409d5469aed47d19e7908d19bd194493aThomas Graf */
900dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put_u8(struct nl_msg *msg, int attrtype, uint8_t value)
90144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
902dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	return nla_put(msg, attrtype, sizeof(uint8_t), &value);
90344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
90444d362409d5469aed47d19e7908d19bd194493aThomas Graf
90544d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
906dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return value of 8 bit integer attribute.
907dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla		8 bit integer attribute
908dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
909dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Payload as 8 bit integer.
91044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
911dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafuint8_t nla_get_u8(struct nlattr *nla)
91244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
913dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	return *(uint8_t *) nla_data(nla);
91444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
91544d362409d5469aed47d19e7908d19bd194493aThomas Graf
91644d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
917dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add 16 bit integer attribute to netlink message.
918dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg		Netlink message.
919dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype	Attribute type.
920dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg value		Numeric value to store as payload.
921dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
922dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_put
923dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code.
92444d362409d5469aed47d19e7908d19bd194493aThomas Graf */
925dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put_u16(struct nl_msg *msg, int attrtype, uint16_t value)
92644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
927dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	return nla_put(msg, attrtype, sizeof(uint16_t), &value);
92844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
92944d362409d5469aed47d19e7908d19bd194493aThomas Graf
93044d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
931dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return payload of 16 bit integer attribute.
932dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla		16 bit integer attribute
933dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
934dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Payload as 16 bit integer.
93544d362409d5469aed47d19e7908d19bd194493aThomas Graf */
936dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafuint16_t nla_get_u16(struct nlattr *nla)
93744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
938dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	return *(uint16_t *) nla_data(nla);
93944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
94044d362409d5469aed47d19e7908d19bd194493aThomas Graf
94144d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
942dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add 32 bit integer attribute to netlink message.
943dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg		Netlink message.
944dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype	Attribute type.
945dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg value		Numeric value to store as payload.
946dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
947dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_put
948dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code.
94944d362409d5469aed47d19e7908d19bd194493aThomas Graf */
950dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put_u32(struct nl_msg *msg, int attrtype, uint32_t value)
95144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
952dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	return nla_put(msg, attrtype, sizeof(uint32_t), &value);
95344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
95444d362409d5469aed47d19e7908d19bd194493aThomas Graf
95544d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
956dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return payload of 32 bit integer attribute.
957dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla		32 bit integer attribute.
958dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
959dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Payload as 32 bit integer.
96044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
961dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafuint32_t nla_get_u32(struct nlattr *nla)
96244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
963dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	return *(uint32_t *) nla_data(nla);
96444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
96544d362409d5469aed47d19e7908d19bd194493aThomas Graf
96644d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
967dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add 64 bit integer attribute to netlink message.
968dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg		Netlink message.
969dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype	Attribute type.
970dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg value		Numeric value to store as payload.
971dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
972dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_put
973dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code.
97444d362409d5469aed47d19e7908d19bd194493aThomas Graf */
975dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put_u64(struct nl_msg *msg, int attrtype, uint64_t value)
97644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
977dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	return nla_put(msg, attrtype, sizeof(uint64_t), &value);
97844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
97944d362409d5469aed47d19e7908d19bd194493aThomas Graf
98044d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
981dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return payload of u64 attribute
982dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla		u64 netlink attribute
983dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
984dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Payload as 64 bit integer.
98544d362409d5469aed47d19e7908d19bd194493aThomas Graf */
986dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafuint64_t nla_get_u64(struct nlattr *nla)
98744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
988dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	uint64_t tmp;
989dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf
990dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	nla_memcpy(&tmp, nla, sizeof(tmp));
991dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf
992dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	return tmp;
99344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
99444d362409d5469aed47d19e7908d19bd194493aThomas Graf
99544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
99644d362409d5469aed47d19e7908d19bd194493aThomas Graf
99744d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
998dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @name String Attribute
99944d362409d5469aed47d19e7908d19bd194493aThomas Graf */
100044d362409d5469aed47d19e7908d19bd194493aThomas Graf
100144d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
1002dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add string attribute to netlink message.
1003dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg		Netlink message.
1004dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype	Attribute type.
1005dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg str		NUL terminated string.
100644d362409d5469aed47d19e7908d19bd194493aThomas Graf *
1007dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_put
1008dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code.
100944d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1010dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put_string(struct nl_msg *msg, int attrtype, const char *str)
101144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
1012dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	return nla_put(msg, attrtype, strlen(str) + 1, str);
101344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
101444d362409d5469aed47d19e7908d19bd194493aThomas Graf
101544d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
1016dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return payload of string attribute.
1017dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla		String attribute.
101844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
1019dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Pointer to attribute payload.
102044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1021dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafchar *nla_get_string(struct nlattr *nla)
102244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
1023dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	return (char *) nla_data(nla);
102444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
102544d362409d5469aed47d19e7908d19bd194493aThomas Graf
1026d49018fd789d96ec3fa90e41af24fd2796bac9feThomas Grafchar *nla_strdup(struct nlattr *nla)
1027d49018fd789d96ec3fa90e41af24fd2796bac9feThomas Graf{
1028d49018fd789d96ec3fa90e41af24fd2796bac9feThomas Graf	return strdup(nla_get_string(nla));
1029d49018fd789d96ec3fa90e41af24fd2796bac9feThomas Graf}
1030d49018fd789d96ec3fa90e41af24fd2796bac9feThomas Graf
103144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
103244d362409d5469aed47d19e7908d19bd194493aThomas Graf
103344d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
1034dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @name Flag Attribute
103544d362409d5469aed47d19e7908d19bd194493aThomas Graf */
103644d362409d5469aed47d19e7908d19bd194493aThomas Graf
103744d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
1038dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add flag netlink attribute to netlink message.
1039dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg		Netlink message.
1040dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype	Attribute type.
1041dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
1042dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_put
1043dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code.
104444d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1045dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put_flag(struct nl_msg *msg, int attrtype)
104644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
1047dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	return nla_put(msg, attrtype, 0, NULL);
104844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
104944d362409d5469aed47d19e7908d19bd194493aThomas Graf
105044d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
1051dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return true if flag attribute is set.
1052dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla		Flag netlink attribute.
1053dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
1054dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return True if flag is set, otherwise false.
105544d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1056dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_get_flag(struct nlattr *nla)
105744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
1058dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	return !!nla;
105944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
106044d362409d5469aed47d19e7908d19bd194493aThomas Graf
1061dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf/** @} */
1062dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf
106344d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
1064dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @name Microseconds Attribute
106544d362409d5469aed47d19e7908d19bd194493aThomas Graf */
106644d362409d5469aed47d19e7908d19bd194493aThomas Graf
106744d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
1068dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add a msecs netlink attribute to a netlink message
1069dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg n		netlink message
1070dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype	attribute type
1071dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msecs 		number of msecs
107244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1073dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put_msecs(struct nl_msg *n, int attrtype, unsigned long msecs)
107444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
1075dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	return nla_put_u64(n, attrtype, msecs);
107644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
107744d362409d5469aed47d19e7908d19bd194493aThomas Graf
107844d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
1079dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Return payload of msecs attribute
1080dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla		msecs netlink attribute
1081dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
1082dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return the number of milliseconds.
108344d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1084dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafunsigned long nla_get_msecs(struct nlattr *nla)
108544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
1086dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	return nla_get_u64(nla);
108744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
108844d362409d5469aed47d19e7908d19bd194493aThomas Graf
1089dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf/** @} */
1090dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf
109144d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
1092dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @name Nested Attribute
109344d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1094dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf
1095dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf/**
1096dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Add nested attributes to netlink message.
1097dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg		Netlink message.
1098dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype	Attribute type.
1099dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nested		Message containing attributes to be nested.
1100dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
1101dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Takes the attributes found in the \a nested message and appends them
1102dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * to the message \a msg nested in a container of the type \a attrtype.
1103dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * The \a nested message may not have a family specific header.
1104dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
1105dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_put
1106dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code.
1107dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf */
1108dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_put_nested(struct nl_msg *msg, int attrtype, struct nl_msg *nested)
110944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
1110dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	return nla_put(msg, attrtype, nlmsg_len(nested->nm_nlh),
1111dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf		       nlmsg_data(nested->nm_nlh));
111244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
111344d362409d5469aed47d19e7908d19bd194493aThomas Graf
1114dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf
111544d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
1116dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Start a new level of nested attributes.
1117dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg		Netlink message.
1118dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg attrtype	Attribute type of container.
111944d362409d5469aed47d19e7908d19bd194493aThomas Graf *
1120dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return Pointer to container attribute.
112144d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1122dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafstruct nlattr *nla_nest_start(struct nl_msg *msg, int attrtype)
112344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
1124dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	struct nlattr *start = (struct nlattr *) nlmsg_tail(msg->nm_nlh);
1125dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf
1126dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	if (nla_put(msg, attrtype, 0, NULL) < 0)
1127dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf		return NULL;
1128dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf
1129dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	return start;
113044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
113144d362409d5469aed47d19e7908d19bd194493aThomas Graf
113244d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
1133dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Finalize nesting of attributes.
1134dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg msg		Netlink message.
1135dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg start		Container attribute as returned from nla_nest_start().
1136dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
1137dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Corrects the container attribute header to include the appeneded attributes.
113844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
1139dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0
114044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1141dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_nest_end(struct nl_msg *msg, struct nlattr *start)
114244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
1143dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	start->nla_len = (unsigned char *) nlmsg_tail(msg->nm_nlh) -
1144dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf				(unsigned char *) start;
1145dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	return 0;
114644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
114744d362409d5469aed47d19e7908d19bd194493aThomas Graf
114844d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
1149dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Create attribute index based on nested attribute
1150dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg tb		Index array to be filled (maxtype+1 elements).
1151dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg maxtype		Maximum attribute type expected and accepted.
1152dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg nla		Nested Attribute.
1153dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @arg policy		Attribute validation policy.
1154dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf *
1155dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * Feeds the stream of attributes nested into the specified attribute
1156dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * to nla_parse().
115744d362409d5469aed47d19e7908d19bd194493aThomas Graf *
1158dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @see nla_parse
1159dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf * @return 0 on success or a negative error code.
116044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1161dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Grafint nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla,
1162dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf		     struct nla_policy *policy)
116344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
1164dbcdf91a99d0e12d012308328bc6e1894403a99bThomas Graf	return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
116544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
116644d362409d5469aed47d19e7908d19bd194493aThomas Graf
116744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
116844d362409d5469aed47d19e7908d19bd194493aThomas Graf
116944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
1170