1*1b481fc3SMaciej Żenczykowski /*
2*1b481fc3SMaciej Żenczykowski * (C) 2008-2012 by Pablo Neira Ayuso <[email protected]>
3*1b481fc3SMaciej Żenczykowski *
4*1b481fc3SMaciej Żenczykowski * This program is free software; you can redistribute it and/or modify
5*1b481fc3SMaciej Żenczykowski * it under the terms of the GNU Lesser General Public License as published
6*1b481fc3SMaciej Żenczykowski * by the Free Software Foundation; either version 2.1 of the License, or
7*1b481fc3SMaciej Żenczykowski * (at your option) any later version.
8*1b481fc3SMaciej Żenczykowski */
9*1b481fc3SMaciej Żenczykowski #include <limits.h> /* for INT_MAX */
10*1b481fc3SMaciej Żenczykowski #include <libmnl/libmnl.h>
11*1b481fc3SMaciej Żenczykowski #include <string.h>
12*1b481fc3SMaciej Żenczykowski #include <errno.h>
13*1b481fc3SMaciej Żenczykowski #include "internal.h"
14*1b481fc3SMaciej Żenczykowski
15*1b481fc3SMaciej Żenczykowski /**
16*1b481fc3SMaciej Żenczykowski * \defgroup attr Netlink attribute helpers
17*1b481fc3SMaciej Żenczykowski *
18*1b481fc3SMaciej Żenczykowski * Netlink Type-Length-Value (TLV) attribute:
19*1b481fc3SMaciej Żenczykowski * \verbatim
20*1b481fc3SMaciej Żenczykowski |<-- 2 bytes -->|<-- 2 bytes -->|<-- variable -->|
21*1b481fc3SMaciej Żenczykowski -------------------------------------------------
22*1b481fc3SMaciej Żenczykowski | length | type | value |
23*1b481fc3SMaciej Żenczykowski -------------------------------------------------
24*1b481fc3SMaciej Żenczykowski |<--------- header ------------>|<-- payload --->|
25*1b481fc3SMaciej Żenczykowski \endverbatim
26*1b481fc3SMaciej Żenczykowski * The payload of the Netlink message contains sequences of attributes that are
27*1b481fc3SMaciej Żenczykowski * expressed in TLV format.
28*1b481fc3SMaciej Żenczykowski *
29*1b481fc3SMaciej Żenczykowski * @{
30*1b481fc3SMaciej Żenczykowski */
31*1b481fc3SMaciej Żenczykowski
32*1b481fc3SMaciej Żenczykowski /**
33*1b481fc3SMaciej Żenczykowski * mnl_attr_get_type - get type of netlink attribute
34*1b481fc3SMaciej Żenczykowski * \param attr pointer to netlink attribute
35*1b481fc3SMaciej Żenczykowski *
36*1b481fc3SMaciej Żenczykowski * \return the attribute type
37*1b481fc3SMaciej Żenczykowski */
mnl_attr_get_type(const struct nlattr * attr)38*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL uint16_t mnl_attr_get_type(const struct nlattr *attr)
39*1b481fc3SMaciej Żenczykowski {
40*1b481fc3SMaciej Żenczykowski return attr->nla_type & NLA_TYPE_MASK;
41*1b481fc3SMaciej Żenczykowski }
42*1b481fc3SMaciej Żenczykowski
43*1b481fc3SMaciej Żenczykowski /**
44*1b481fc3SMaciej Żenczykowski * mnl_attr_get_len - get length of netlink attribute
45*1b481fc3SMaciej Żenczykowski * \param attr pointer to netlink attribute
46*1b481fc3SMaciej Żenczykowski *
47*1b481fc3SMaciej Żenczykowski * \return the attribute length
48*1b481fc3SMaciej Żenczykowski *
49*1b481fc3SMaciej Żenczykowski * The attribute length is the length of the attribute header plus the
50*1b481fc3SMaciej Żenczykowski * attribute payload.
51*1b481fc3SMaciej Żenczykowski *
52*1b481fc3SMaciej Żenczykowski */
mnl_attr_get_len(const struct nlattr * attr)53*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL uint16_t mnl_attr_get_len(const struct nlattr *attr)
54*1b481fc3SMaciej Żenczykowski {
55*1b481fc3SMaciej Żenczykowski return attr->nla_len;
56*1b481fc3SMaciej Żenczykowski }
57*1b481fc3SMaciej Żenczykowski
58*1b481fc3SMaciej Żenczykowski /**
59*1b481fc3SMaciej Żenczykowski * mnl_attr_get_payload_len - get the attribute payload-value length
60*1b481fc3SMaciej Żenczykowski * \param attr pointer to netlink attribute
61*1b481fc3SMaciej Żenczykowski *
62*1b481fc3SMaciej Żenczykowski * \return the attribute payload-value length
63*1b481fc3SMaciej Żenczykowski */
mnl_attr_get_payload_len(const struct nlattr * attr)64*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL uint16_t mnl_attr_get_payload_len(const struct nlattr *attr)
65*1b481fc3SMaciej Żenczykowski {
66*1b481fc3SMaciej Żenczykowski return attr->nla_len - MNL_ATTR_HDRLEN;
67*1b481fc3SMaciej Żenczykowski }
68*1b481fc3SMaciej Żenczykowski
69*1b481fc3SMaciej Żenczykowski /**
70*1b481fc3SMaciej Żenczykowski * mnl_attr_get_payload - get pointer to the attribute payload
71*1b481fc3SMaciej Żenczykowski * \param attr pointer to netlink attribute
72*1b481fc3SMaciej Żenczykowski *
73*1b481fc3SMaciej Żenczykowski * \return pointer to the attribute payload
74*1b481fc3SMaciej Żenczykowski */
mnl_attr_get_payload(const struct nlattr * attr)75*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL void *mnl_attr_get_payload(const struct nlattr *attr)
76*1b481fc3SMaciej Żenczykowski {
77*1b481fc3SMaciej Żenczykowski return (void *)attr + MNL_ATTR_HDRLEN;
78*1b481fc3SMaciej Żenczykowski }
79*1b481fc3SMaciej Żenczykowski
80*1b481fc3SMaciej Żenczykowski /**
81*1b481fc3SMaciej Żenczykowski * mnl_attr_ok - check if there is room for an attribute in a buffer
82*1b481fc3SMaciej Żenczykowski * \param attr attribute that we want to check if there is room for
83*1b481fc3SMaciej Żenczykowski * \param len remaining bytes in a buffer that contains the attribute
84*1b481fc3SMaciej Żenczykowski *
85*1b481fc3SMaciej Żenczykowski * This function is used to check that a buffer, which is supposed to contain
86*1b481fc3SMaciej Żenczykowski * an attribute, has enough room for the attribute that it stores, i.e. this
87*1b481fc3SMaciej Żenczykowski * function can be used to verify that an attribute is neither malformed nor
88*1b481fc3SMaciej Żenczykowski * truncated.
89*1b481fc3SMaciej Żenczykowski *
90*1b481fc3SMaciej Żenczykowski * This function does not set errno in case of error since it is intended
91*1b481fc3SMaciej Żenczykowski * for iterations.
92*1b481fc3SMaciej Żenczykowski *
93*1b481fc3SMaciej Żenczykowski * The len parameter may be negative in the case of malformed messages during
94*1b481fc3SMaciej Żenczykowski * attribute iteration, that is why we use a signed integer.
95*1b481fc3SMaciej Żenczykowski *
96*1b481fc3SMaciej Żenczykowski * \return true if there is room for the attribute, false otherwise
97*1b481fc3SMaciej Żenczykowski */
mnl_attr_ok(const struct nlattr * attr,int len)98*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL bool mnl_attr_ok(const struct nlattr *attr, int len)
99*1b481fc3SMaciej Żenczykowski {
100*1b481fc3SMaciej Żenczykowski return len >= (int)sizeof(struct nlattr) &&
101*1b481fc3SMaciej Żenczykowski attr->nla_len >= sizeof(struct nlattr) &&
102*1b481fc3SMaciej Żenczykowski (int)attr->nla_len <= len;
103*1b481fc3SMaciej Żenczykowski }
104*1b481fc3SMaciej Żenczykowski
105*1b481fc3SMaciej Żenczykowski /**
106*1b481fc3SMaciej Żenczykowski * mnl_attr_next - get the next attribute in the payload of a netlink message
107*1b481fc3SMaciej Żenczykowski * \param attr pointer to the current attribute
108*1b481fc3SMaciej Żenczykowski *
109*1b481fc3SMaciej Żenczykowski * \return a pointer to the next attribute after the one passed in
110*1b481fc3SMaciej Żenczykowski *
111*1b481fc3SMaciej Żenczykowski * You have to use mnl_attr_ok() on the returned attribute to ensure that the
112*1b481fc3SMaciej Żenczykowski * next attribute is valid.
113*1b481fc3SMaciej Żenczykowski *
114*1b481fc3SMaciej Żenczykowski */
mnl_attr_next(const struct nlattr * attr)115*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL struct nlattr *mnl_attr_next(const struct nlattr *attr)
116*1b481fc3SMaciej Żenczykowski {
117*1b481fc3SMaciej Żenczykowski return (struct nlattr *)((void *)attr + MNL_ALIGN(attr->nla_len));
118*1b481fc3SMaciej Żenczykowski }
119*1b481fc3SMaciej Żenczykowski
120*1b481fc3SMaciej Żenczykowski /**
121*1b481fc3SMaciej Żenczykowski * mnl_attr_type_valid - check if the attribute type is valid
122*1b481fc3SMaciej Żenczykowski * \param attr pointer to attribute to be checked
123*1b481fc3SMaciej Żenczykowski * \param max maximum attribute type
124*1b481fc3SMaciej Żenczykowski *
125*1b481fc3SMaciej Żenczykowski * This function allows one to check if the attribute type is higher than the
126*1b481fc3SMaciej Żenczykowski * maximum supported type.
127*1b481fc3SMaciej Żenczykowski *
128*1b481fc3SMaciej Żenczykowski * Strict attribute checking in user-space is not a good idea since you may
129*1b481fc3SMaciej Żenczykowski * run an old application with a newer kernel that supports new attributes.
130*1b481fc3SMaciej Żenczykowski * This leads to backward compatibility breakages in user-space. Better check
131*1b481fc3SMaciej Żenczykowski * if you support an attribute, if not, skip it.
132*1b481fc3SMaciej Żenczykowski *
133*1b481fc3SMaciej Żenczykowski * On an error, errno is explicitly set.
134*1b481fc3SMaciej Żenczykowski *
135*1b481fc3SMaciej Żenczykowski * \return 1 if the attribute is valid, -1 otherwise
136*1b481fc3SMaciej Żenczykowski *
137*1b481fc3SMaciej Żenczykowski */
mnl_attr_type_valid(const struct nlattr * attr,uint16_t max)138*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL int mnl_attr_type_valid(const struct nlattr *attr, uint16_t max)
139*1b481fc3SMaciej Żenczykowski {
140*1b481fc3SMaciej Żenczykowski if (mnl_attr_get_type(attr) > max) {
141*1b481fc3SMaciej Żenczykowski errno = EOPNOTSUPP;
142*1b481fc3SMaciej Żenczykowski return -1;
143*1b481fc3SMaciej Żenczykowski }
144*1b481fc3SMaciej Żenczykowski return 1;
145*1b481fc3SMaciej Żenczykowski }
146*1b481fc3SMaciej Żenczykowski
__mnl_attr_validate(const struct nlattr * attr,enum mnl_attr_data_type type,size_t exp_len)147*1b481fc3SMaciej Żenczykowski static int __mnl_attr_validate(const struct nlattr *attr,
148*1b481fc3SMaciej Żenczykowski enum mnl_attr_data_type type, size_t exp_len)
149*1b481fc3SMaciej Żenczykowski {
150*1b481fc3SMaciej Żenczykowski uint16_t attr_len = mnl_attr_get_payload_len(attr);
151*1b481fc3SMaciej Żenczykowski const char *attr_data = mnl_attr_get_payload(attr);
152*1b481fc3SMaciej Żenczykowski
153*1b481fc3SMaciej Żenczykowski if (attr_len < exp_len) {
154*1b481fc3SMaciej Żenczykowski errno = ERANGE;
155*1b481fc3SMaciej Żenczykowski return -1;
156*1b481fc3SMaciej Żenczykowski }
157*1b481fc3SMaciej Żenczykowski switch(type) {
158*1b481fc3SMaciej Żenczykowski case MNL_TYPE_FLAG:
159*1b481fc3SMaciej Żenczykowski if (attr_len > 0) {
160*1b481fc3SMaciej Żenczykowski errno = ERANGE;
161*1b481fc3SMaciej Żenczykowski return -1;
162*1b481fc3SMaciej Żenczykowski }
163*1b481fc3SMaciej Żenczykowski break;
164*1b481fc3SMaciej Żenczykowski case MNL_TYPE_NUL_STRING:
165*1b481fc3SMaciej Żenczykowski if (attr_len == 0) {
166*1b481fc3SMaciej Żenczykowski errno = ERANGE;
167*1b481fc3SMaciej Żenczykowski return -1;
168*1b481fc3SMaciej Żenczykowski }
169*1b481fc3SMaciej Żenczykowski if (attr_data[attr_len-1] != '\0') {
170*1b481fc3SMaciej Żenczykowski errno = EINVAL;
171*1b481fc3SMaciej Żenczykowski return -1;
172*1b481fc3SMaciej Żenczykowski }
173*1b481fc3SMaciej Żenczykowski break;
174*1b481fc3SMaciej Żenczykowski case MNL_TYPE_STRING:
175*1b481fc3SMaciej Żenczykowski if (attr_len == 0) {
176*1b481fc3SMaciej Żenczykowski errno = ERANGE;
177*1b481fc3SMaciej Żenczykowski return -1;
178*1b481fc3SMaciej Żenczykowski }
179*1b481fc3SMaciej Żenczykowski break;
180*1b481fc3SMaciej Żenczykowski case MNL_TYPE_NESTED:
181*1b481fc3SMaciej Żenczykowski /* empty nested attributes are OK. */
182*1b481fc3SMaciej Żenczykowski if (attr_len == 0)
183*1b481fc3SMaciej Żenczykowski break;
184*1b481fc3SMaciej Żenczykowski /* if not empty, they must contain one header, eg. flag */
185*1b481fc3SMaciej Żenczykowski if (attr_len < MNL_ATTR_HDRLEN) {
186*1b481fc3SMaciej Żenczykowski errno = ERANGE;
187*1b481fc3SMaciej Żenczykowski return -1;
188*1b481fc3SMaciej Żenczykowski }
189*1b481fc3SMaciej Żenczykowski break;
190*1b481fc3SMaciej Żenczykowski default:
191*1b481fc3SMaciej Żenczykowski /* make gcc happy. */
192*1b481fc3SMaciej Żenczykowski break;
193*1b481fc3SMaciej Żenczykowski }
194*1b481fc3SMaciej Żenczykowski if (exp_len && attr_len > exp_len) {
195*1b481fc3SMaciej Żenczykowski errno = ERANGE;
196*1b481fc3SMaciej Żenczykowski return -1;
197*1b481fc3SMaciej Żenczykowski }
198*1b481fc3SMaciej Żenczykowski return 0;
199*1b481fc3SMaciej Żenczykowski }
200*1b481fc3SMaciej Żenczykowski
201*1b481fc3SMaciej Żenczykowski static const size_t mnl_attr_data_type_len[MNL_TYPE_MAX] = {
202*1b481fc3SMaciej Żenczykowski [MNL_TYPE_U8] = sizeof(uint8_t),
203*1b481fc3SMaciej Żenczykowski [MNL_TYPE_U16] = sizeof(uint16_t),
204*1b481fc3SMaciej Żenczykowski [MNL_TYPE_U32] = sizeof(uint32_t),
205*1b481fc3SMaciej Żenczykowski [MNL_TYPE_U64] = sizeof(uint64_t),
206*1b481fc3SMaciej Żenczykowski [MNL_TYPE_MSECS] = sizeof(uint64_t),
207*1b481fc3SMaciej Żenczykowski };
208*1b481fc3SMaciej Żenczykowski
209*1b481fc3SMaciej Żenczykowski /**
210*1b481fc3SMaciej Żenczykowski * mnl_attr_validate - validate netlink attribute (simplified version)
211*1b481fc3SMaciej Żenczykowski * \param attr pointer to netlink attribute that we want to validate
212*1b481fc3SMaciej Żenczykowski * \param type data type (see enum mnl_attr_data_type)
213*1b481fc3SMaciej Żenczykowski *
214*1b481fc3SMaciej Żenczykowski * The validation is based on the data type. Specifically, it checks that
215*1b481fc3SMaciej Żenczykowski * integers (u8, u16, u32 and u64) have enough room for them.
216*1b481fc3SMaciej Żenczykowski *
217*1b481fc3SMaciej Żenczykowski * On an error, errno is explicitly set.
218*1b481fc3SMaciej Żenczykowski *
219*1b481fc3SMaciej Żenczykowski * \return 0 on success, -1 on error
220*1b481fc3SMaciej Żenczykowski */
mnl_attr_validate(const struct nlattr * attr,enum mnl_attr_data_type type)221*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type)
222*1b481fc3SMaciej Żenczykowski {
223*1b481fc3SMaciej Żenczykowski int exp_len;
224*1b481fc3SMaciej Żenczykowski
225*1b481fc3SMaciej Żenczykowski if (type >= MNL_TYPE_MAX) {
226*1b481fc3SMaciej Żenczykowski errno = EINVAL;
227*1b481fc3SMaciej Żenczykowski return -1;
228*1b481fc3SMaciej Żenczykowski }
229*1b481fc3SMaciej Żenczykowski exp_len = mnl_attr_data_type_len[type];
230*1b481fc3SMaciej Żenczykowski return __mnl_attr_validate(attr, type, exp_len);
231*1b481fc3SMaciej Żenczykowski }
232*1b481fc3SMaciej Żenczykowski
233*1b481fc3SMaciej Żenczykowski /**
234*1b481fc3SMaciej Żenczykowski * mnl_attr_validate2 - validate netlink attribute (extended version)
235*1b481fc3SMaciej Żenczykowski * \param attr pointer to netlink attribute that we want to validate
236*1b481fc3SMaciej Żenczykowski * \param type attribute type (see enum mnl_attr_data_type)
237*1b481fc3SMaciej Żenczykowski * \param exp_len expected attribute data size
238*1b481fc3SMaciej Żenczykowski *
239*1b481fc3SMaciej Żenczykowski * This function allows one to perform a more accurate validation for attributes
240*1b481fc3SMaciej Żenczykowski * whose size is variable.
241*1b481fc3SMaciej Żenczykowski *
242*1b481fc3SMaciej Żenczykowski * On an error, errno is explicitly set.
243*1b481fc3SMaciej Żenczykowski *
244*1b481fc3SMaciej Żenczykowski * \return 0 if the attribute is valid and fits within the expected length, -1
245*1b481fc3SMaciej Żenczykowski * otherwise
246*1b481fc3SMaciej Żenczykowski */
mnl_attr_validate2(const struct nlattr * attr,enum mnl_attr_data_type type,size_t exp_len)247*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL int mnl_attr_validate2(const struct nlattr *attr,
248*1b481fc3SMaciej Żenczykowski enum mnl_attr_data_type type,
249*1b481fc3SMaciej Żenczykowski size_t exp_len)
250*1b481fc3SMaciej Żenczykowski {
251*1b481fc3SMaciej Żenczykowski if (type >= MNL_TYPE_MAX) {
252*1b481fc3SMaciej Żenczykowski errno = EINVAL;
253*1b481fc3SMaciej Żenczykowski return -1;
254*1b481fc3SMaciej Żenczykowski }
255*1b481fc3SMaciej Żenczykowski return __mnl_attr_validate(attr, type, exp_len);
256*1b481fc3SMaciej Żenczykowski }
257*1b481fc3SMaciej Żenczykowski
258*1b481fc3SMaciej Żenczykowski /**
259*1b481fc3SMaciej Żenczykowski * mnl_attr_parse - parse attributes
260*1b481fc3SMaciej Żenczykowski * \param nlh pointer to netlink message
261*1b481fc3SMaciej Żenczykowski * \param offset offset to start parsing from (if payload is after any header)
262*1b481fc3SMaciej Żenczykowski * \param cb callback function that is called for each attribute
263*1b481fc3SMaciej Żenczykowski * \param data pointer to data that is passed to the callback function
264*1b481fc3SMaciej Żenczykowski *
265*1b481fc3SMaciej Żenczykowski * This function allows you to iterate over the sequence of attributes that
266*1b481fc3SMaciej Żenczykowski * compose the Netlink message. You can then put the attribute in an array as it
267*1b481fc3SMaciej Żenczykowski * usually happens at this stage or you can use any other data structure (such
268*1b481fc3SMaciej Żenczykowski * as lists or trees).
269*1b481fc3SMaciej Żenczykowski *
270*1b481fc3SMaciej Żenczykowski * \return propagated value from callback, one of MNL_CB_ERROR, MNL_CB_STOP
271*1b481fc3SMaciej Żenczykowski * or MNL_CB_OK
272*1b481fc3SMaciej Żenczykowski */
mnl_attr_parse(const struct nlmsghdr * nlh,unsigned int offset,mnl_attr_cb_t cb,void * data)273*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL int mnl_attr_parse(const struct nlmsghdr *nlh,
274*1b481fc3SMaciej Żenczykowski unsigned int offset, mnl_attr_cb_t cb,
275*1b481fc3SMaciej Żenczykowski void *data)
276*1b481fc3SMaciej Żenczykowski {
277*1b481fc3SMaciej Żenczykowski int ret = MNL_CB_OK;
278*1b481fc3SMaciej Żenczykowski const struct nlattr *attr;
279*1b481fc3SMaciej Żenczykowski
280*1b481fc3SMaciej Żenczykowski mnl_attr_for_each(attr, nlh, offset)
281*1b481fc3SMaciej Żenczykowski if ((ret = cb(attr, data)) <= MNL_CB_STOP)
282*1b481fc3SMaciej Żenczykowski return ret;
283*1b481fc3SMaciej Żenczykowski return ret;
284*1b481fc3SMaciej Żenczykowski }
285*1b481fc3SMaciej Żenczykowski
286*1b481fc3SMaciej Żenczykowski /**
287*1b481fc3SMaciej Żenczykowski * mnl_attr_parse_nested - parse attributes inside a nest
288*1b481fc3SMaciej Żenczykowski * \param nested pointer to netlink attribute that contains a nest
289*1b481fc3SMaciej Żenczykowski * \param cb callback function that is called for each attribute in the nest
290*1b481fc3SMaciej Żenczykowski * \param data pointer to data passed to the callback function
291*1b481fc3SMaciej Żenczykowski *
292*1b481fc3SMaciej Żenczykowski * This function allows you to iterate over the sequence of attributes that
293*1b481fc3SMaciej Żenczykowski * compose the Netlink message. You can then put the attribute in an array as it
294*1b481fc3SMaciej Żenczykowski * usually happens at this stage or you can use any other data structure (such
295*1b481fc3SMaciej Żenczykowski * as lists or trees).
296*1b481fc3SMaciej Żenczykowski *
297*1b481fc3SMaciej Żenczykowski * \return propagated value from callback, one of MNL_CB_ERROR, MNL_CB_STOP
298*1b481fc3SMaciej Żenczykowski * or MNL_CB_OK
299*1b481fc3SMaciej Żenczykowski */
mnl_attr_parse_nested(const struct nlattr * nested,mnl_attr_cb_t cb,void * data)300*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL int mnl_attr_parse_nested(const struct nlattr *nested,
301*1b481fc3SMaciej Żenczykowski mnl_attr_cb_t cb, void *data)
302*1b481fc3SMaciej Żenczykowski {
303*1b481fc3SMaciej Żenczykowski int ret = MNL_CB_OK;
304*1b481fc3SMaciej Żenczykowski const struct nlattr *attr;
305*1b481fc3SMaciej Żenczykowski
306*1b481fc3SMaciej Żenczykowski mnl_attr_for_each_nested(attr, nested)
307*1b481fc3SMaciej Żenczykowski if ((ret = cb(attr, data)) <= MNL_CB_STOP)
308*1b481fc3SMaciej Żenczykowski return ret;
309*1b481fc3SMaciej Żenczykowski return ret;
310*1b481fc3SMaciej Żenczykowski }
311*1b481fc3SMaciej Żenczykowski
312*1b481fc3SMaciej Żenczykowski /**
313*1b481fc3SMaciej Żenczykowski * mnl_attr_parse_payload - parse attributes in payload of Netlink message
314*1b481fc3SMaciej Żenczykowski * \param payload pointer to payload of the Netlink message
315*1b481fc3SMaciej Żenczykowski * \param payload_len payload length that contains the attributes
316*1b481fc3SMaciej Żenczykowski * \param cb callback function that is called for each attribute
317*1b481fc3SMaciej Żenczykowski * \param data pointer to data that is passed to the callback function
318*1b481fc3SMaciej Żenczykowski *
319*1b481fc3SMaciej Żenczykowski * This function takes a pointer to the area that contains the attributes,
320*1b481fc3SMaciej Żenczykowski * commonly known as the payload of the Netlink message. Thus, you have to
321*1b481fc3SMaciej Żenczykowski * pass a pointer to the Netlink message payload, instead of the entire
322*1b481fc3SMaciej Żenczykowski * message.
323*1b481fc3SMaciej Żenczykowski *
324*1b481fc3SMaciej Żenczykowski * This function allows you to iterate over the sequence of attributes that are
325*1b481fc3SMaciej Żenczykowski * located at some payload offset. You can then put the attributes in one array
326*1b481fc3SMaciej Żenczykowski * as usual, or you can use any other data structure (such as lists or trees).
327*1b481fc3SMaciej Żenczykowski *
328*1b481fc3SMaciej Żenczykowski * \return propagated value from callback, one of MNL_CB_ERROR, MNL_CB_STOP
329*1b481fc3SMaciej Żenczykowski * or MNL_CB_OK
330*1b481fc3SMaciej Żenczykowski */
mnl_attr_parse_payload(const void * payload,size_t payload_len,mnl_attr_cb_t cb,void * data)331*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL int mnl_attr_parse_payload(const void *payload,
332*1b481fc3SMaciej Żenczykowski size_t payload_len,
333*1b481fc3SMaciej Żenczykowski mnl_attr_cb_t cb, void *data)
334*1b481fc3SMaciej Żenczykowski {
335*1b481fc3SMaciej Żenczykowski int ret = MNL_CB_OK;
336*1b481fc3SMaciej Żenczykowski const struct nlattr *attr;
337*1b481fc3SMaciej Żenczykowski
338*1b481fc3SMaciej Żenczykowski mnl_attr_for_each_payload(payload, payload_len)
339*1b481fc3SMaciej Żenczykowski if ((ret = cb(attr, data)) <= MNL_CB_STOP)
340*1b481fc3SMaciej Żenczykowski return ret;
341*1b481fc3SMaciej Żenczykowski return ret;
342*1b481fc3SMaciej Żenczykowski }
343*1b481fc3SMaciej Żenczykowski
344*1b481fc3SMaciej Żenczykowski /**
345*1b481fc3SMaciej Żenczykowski * mnl_attr_get_u8 - get 8-bit unsigned integer attribute payload
346*1b481fc3SMaciej Żenczykowski * \param attr pointer to netlink attribute
347*1b481fc3SMaciej Żenczykowski *
348*1b481fc3SMaciej Żenczykowski * \return 8-bit value of the attribute payload
349*1b481fc3SMaciej Żenczykowski */
mnl_attr_get_u8(const struct nlattr * attr)350*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL uint8_t mnl_attr_get_u8(const struct nlattr *attr)
351*1b481fc3SMaciej Żenczykowski {
352*1b481fc3SMaciej Żenczykowski return *((uint8_t *)mnl_attr_get_payload(attr));
353*1b481fc3SMaciej Żenczykowski }
354*1b481fc3SMaciej Żenczykowski
355*1b481fc3SMaciej Żenczykowski /**
356*1b481fc3SMaciej Żenczykowski * mnl_attr_get_u16 - get 16-bit unsigned integer attribute payload
357*1b481fc3SMaciej Żenczykowski * \param attr pointer to netlink attribute
358*1b481fc3SMaciej Żenczykowski *
359*1b481fc3SMaciej Żenczykowski * \return 16-bit value of the attribute payload
360*1b481fc3SMaciej Żenczykowski */
mnl_attr_get_u16(const struct nlattr * attr)361*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL uint16_t mnl_attr_get_u16(const struct nlattr *attr)
362*1b481fc3SMaciej Żenczykowski {
363*1b481fc3SMaciej Żenczykowski return *((uint16_t *)mnl_attr_get_payload(attr));
364*1b481fc3SMaciej Żenczykowski }
365*1b481fc3SMaciej Żenczykowski
366*1b481fc3SMaciej Żenczykowski /**
367*1b481fc3SMaciej Żenczykowski * mnl_attr_get_u32 - get 32-bit unsigned integer attribute payload
368*1b481fc3SMaciej Żenczykowski * \param attr pointer to netlink attribute
369*1b481fc3SMaciej Żenczykowski *
370*1b481fc3SMaciej Żenczykowski * \return 32-bit value of the attribute payload
371*1b481fc3SMaciej Żenczykowski */
mnl_attr_get_u32(const struct nlattr * attr)372*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL uint32_t mnl_attr_get_u32(const struct nlattr *attr)
373*1b481fc3SMaciej Żenczykowski {
374*1b481fc3SMaciej Żenczykowski return *((uint32_t *)mnl_attr_get_payload(attr));
375*1b481fc3SMaciej Żenczykowski }
376*1b481fc3SMaciej Żenczykowski
377*1b481fc3SMaciej Żenczykowski /**
378*1b481fc3SMaciej Żenczykowski * mnl_attr_get_u64 - get 64-bit unsigned integer attribute
379*1b481fc3SMaciej Żenczykowski * \param attr pointer to netlink attribute
380*1b481fc3SMaciej Żenczykowski *
381*1b481fc3SMaciej Żenczykowski * This function reads the 64-bit nlattr payload in an alignment safe manner.
382*1b481fc3SMaciej Żenczykowski *
383*1b481fc3SMaciej Żenczykowski * \return 64-bit value of the attribute payload
384*1b481fc3SMaciej Żenczykowski */
mnl_attr_get_u64(const struct nlattr * attr)385*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL uint64_t mnl_attr_get_u64(const struct nlattr *attr)
386*1b481fc3SMaciej Żenczykowski {
387*1b481fc3SMaciej Żenczykowski uint64_t tmp;
388*1b481fc3SMaciej Żenczykowski memcpy(&tmp, mnl_attr_get_payload(attr), sizeof(tmp));
389*1b481fc3SMaciej Żenczykowski return tmp;
390*1b481fc3SMaciej Żenczykowski }
391*1b481fc3SMaciej Żenczykowski
392*1b481fc3SMaciej Żenczykowski /**
393*1b481fc3SMaciej Żenczykowski * mnl_attr_get_str - get pointer to string attribute
394*1b481fc3SMaciej Żenczykowski * \param attr pointer to netlink attribute
395*1b481fc3SMaciej Żenczykowski *
396*1b481fc3SMaciej Żenczykowski * \return string pointer of the attribute payload
397*1b481fc3SMaciej Żenczykowski */
mnl_attr_get_str(const struct nlattr * attr)398*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL const char *mnl_attr_get_str(const struct nlattr *attr)
399*1b481fc3SMaciej Żenczykowski {
400*1b481fc3SMaciej Żenczykowski return mnl_attr_get_payload(attr);
401*1b481fc3SMaciej Żenczykowski }
402*1b481fc3SMaciej Żenczykowski
403*1b481fc3SMaciej Żenczykowski /**
404*1b481fc3SMaciej Żenczykowski * mnl_attr_put - add an attribute to netlink message
405*1b481fc3SMaciej Żenczykowski * \param nlh pointer to the netlink message
406*1b481fc3SMaciej Żenczykowski * \param type netlink attribute type that you want to add
407*1b481fc3SMaciej Żenczykowski * \param len netlink attribute payload length
408*1b481fc3SMaciej Żenczykowski * \param data pointer to the data that will be stored by the new attribute
409*1b481fc3SMaciej Żenczykowski *
410*1b481fc3SMaciej Żenczykowski * This function updates the length field of the Netlink message (nlmsg_len)
411*1b481fc3SMaciej Żenczykowski * by adding the size (header + payload) of the new attribute.
412*1b481fc3SMaciej Żenczykowski */
mnl_attr_put(struct nlmsghdr * nlh,uint16_t type,size_t len,const void * data)413*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type,
414*1b481fc3SMaciej Żenczykowski size_t len, const void *data)
415*1b481fc3SMaciej Żenczykowski {
416*1b481fc3SMaciej Żenczykowski struct nlattr *attr = mnl_nlmsg_get_payload_tail(nlh);
417*1b481fc3SMaciej Żenczykowski uint16_t payload_len = MNL_ALIGN(sizeof(struct nlattr)) + len;
418*1b481fc3SMaciej Żenczykowski int pad;
419*1b481fc3SMaciej Żenczykowski
420*1b481fc3SMaciej Żenczykowski attr->nla_type = type;
421*1b481fc3SMaciej Żenczykowski attr->nla_len = payload_len;
422*1b481fc3SMaciej Żenczykowski memcpy(mnl_attr_get_payload(attr), data, len);
423*1b481fc3SMaciej Żenczykowski pad = MNL_ALIGN(len) - len;
424*1b481fc3SMaciej Żenczykowski if (pad > 0)
425*1b481fc3SMaciej Żenczykowski memset(mnl_attr_get_payload(attr) + len, 0, pad);
426*1b481fc3SMaciej Żenczykowski
427*1b481fc3SMaciej Żenczykowski nlh->nlmsg_len += MNL_ALIGN(payload_len);
428*1b481fc3SMaciej Żenczykowski }
429*1b481fc3SMaciej Żenczykowski
430*1b481fc3SMaciej Żenczykowski /**
431*1b481fc3SMaciej Żenczykowski * mnl_attr_put_u8 - add 8-bit unsigned integer attribute to netlink message
432*1b481fc3SMaciej Żenczykowski * \param nlh pointer to the netlink message
433*1b481fc3SMaciej Żenczykowski * \param type netlink attribute type
434*1b481fc3SMaciej Żenczykowski * \param data 8-bit unsigned integer data that is stored by the new attribute
435*1b481fc3SMaciej Żenczykowski *
436*1b481fc3SMaciej Żenczykowski * This function updates the length field of the Netlink message (nlmsg_len)
437*1b481fc3SMaciej Żenczykowski * by adding the size (header + payload) of the new attribute.
438*1b481fc3SMaciej Żenczykowski */
mnl_attr_put_u8(struct nlmsghdr * nlh,uint16_t type,uint8_t data)439*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL void mnl_attr_put_u8(struct nlmsghdr *nlh, uint16_t type,
440*1b481fc3SMaciej Żenczykowski uint8_t data)
441*1b481fc3SMaciej Żenczykowski {
442*1b481fc3SMaciej Żenczykowski mnl_attr_put(nlh, type, sizeof(uint8_t), &data);
443*1b481fc3SMaciej Żenczykowski }
444*1b481fc3SMaciej Żenczykowski
445*1b481fc3SMaciej Żenczykowski /**
446*1b481fc3SMaciej Żenczykowski * mnl_attr_put_u16 - add 16-bit unsigned integer attribute to netlink message
447*1b481fc3SMaciej Żenczykowski * \param nlh pointer to the netlink message
448*1b481fc3SMaciej Żenczykowski * \param type netlink attribute type
449*1b481fc3SMaciej Żenczykowski * \param data 16-bit unsigned integer data that is stored by the new attribute
450*1b481fc3SMaciej Żenczykowski *
451*1b481fc3SMaciej Żenczykowski * This function updates the length field of the Netlink message (nlmsg_len)
452*1b481fc3SMaciej Żenczykowski * by adding the size (header + payload) of the new attribute.
453*1b481fc3SMaciej Żenczykowski */
mnl_attr_put_u16(struct nlmsghdr * nlh,uint16_t type,uint16_t data)454*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type,
455*1b481fc3SMaciej Żenczykowski uint16_t data)
456*1b481fc3SMaciej Żenczykowski {
457*1b481fc3SMaciej Żenczykowski mnl_attr_put(nlh, type, sizeof(uint16_t), &data);
458*1b481fc3SMaciej Żenczykowski }
459*1b481fc3SMaciej Żenczykowski
460*1b481fc3SMaciej Żenczykowski /**
461*1b481fc3SMaciej Żenczykowski * mnl_attr_put_u32 - add 32-bit unsigned integer attribute to netlink message
462*1b481fc3SMaciej Żenczykowski * \param nlh pointer to the netlink message
463*1b481fc3SMaciej Żenczykowski * \param type netlink attribute type
464*1b481fc3SMaciej Żenczykowski * \param data 32-bit unsigned integer data that is stored by the new attribute
465*1b481fc3SMaciej Żenczykowski *
466*1b481fc3SMaciej Żenczykowski * This function updates the length field of the Netlink message (nlmsg_len)
467*1b481fc3SMaciej Żenczykowski * by adding the size (header + payload) of the new attribute.
468*1b481fc3SMaciej Żenczykowski */
mnl_attr_put_u32(struct nlmsghdr * nlh,uint16_t type,uint32_t data)469*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type,
470*1b481fc3SMaciej Żenczykowski uint32_t data)
471*1b481fc3SMaciej Żenczykowski {
472*1b481fc3SMaciej Żenczykowski mnl_attr_put(nlh, type, sizeof(uint32_t), &data);
473*1b481fc3SMaciej Żenczykowski }
474*1b481fc3SMaciej Żenczykowski
475*1b481fc3SMaciej Żenczykowski /**
476*1b481fc3SMaciej Żenczykowski * mnl_attr_put_u64 - add 64-bit unsigned integer attribute to netlink message
477*1b481fc3SMaciej Żenczykowski * \param nlh pointer to the netlink message
478*1b481fc3SMaciej Żenczykowski * \param type netlink attribute type
479*1b481fc3SMaciej Żenczykowski * \param data 64-bit unsigned integer data that is stored by the new attribute
480*1b481fc3SMaciej Żenczykowski *
481*1b481fc3SMaciej Żenczykowski * This function updates the length field of the Netlink message (nlmsg_len)
482*1b481fc3SMaciej Żenczykowski * by adding the size (header + payload) of the new attribute.
483*1b481fc3SMaciej Żenczykowski */
mnl_attr_put_u64(struct nlmsghdr * nlh,uint16_t type,uint64_t data)484*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL void mnl_attr_put_u64(struct nlmsghdr *nlh, uint16_t type,
485*1b481fc3SMaciej Żenczykowski uint64_t data)
486*1b481fc3SMaciej Żenczykowski {
487*1b481fc3SMaciej Żenczykowski mnl_attr_put(nlh, type, sizeof(uint64_t), &data);
488*1b481fc3SMaciej Żenczykowski }
489*1b481fc3SMaciej Żenczykowski
490*1b481fc3SMaciej Żenczykowski /**
491*1b481fc3SMaciej Żenczykowski * mnl_attr_put_str - add string attribute to netlink message
492*1b481fc3SMaciej Żenczykowski * \param nlh pointer to the netlink message
493*1b481fc3SMaciej Żenczykowski * \param type netlink attribute type
494*1b481fc3SMaciej Żenczykowski * \param data pointer to string data that is stored by the new attribute
495*1b481fc3SMaciej Żenczykowski *
496*1b481fc3SMaciej Żenczykowski * This function updates the length field of the Netlink message (nlmsg_len)
497*1b481fc3SMaciej Żenczykowski * by adding the size (header + payload) of the new attribute.
498*1b481fc3SMaciej Żenczykowski */
mnl_attr_put_str(struct nlmsghdr * nlh,uint16_t type,const char * data)499*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL void mnl_attr_put_str(struct nlmsghdr *nlh, uint16_t type,
500*1b481fc3SMaciej Żenczykowski const char *data)
501*1b481fc3SMaciej Żenczykowski {
502*1b481fc3SMaciej Żenczykowski mnl_attr_put(nlh, type, strlen(data), data);
503*1b481fc3SMaciej Żenczykowski }
504*1b481fc3SMaciej Żenczykowski
505*1b481fc3SMaciej Żenczykowski /**
506*1b481fc3SMaciej Żenczykowski * mnl_attr_put_strz - add string attribute to netlink message
507*1b481fc3SMaciej Żenczykowski * \param nlh pointer to the netlink message
508*1b481fc3SMaciej Żenczykowski * \param type netlink attribute type
509*1b481fc3SMaciej Żenczykowski * \param data pointer to string data that is stored by the new attribute
510*1b481fc3SMaciej Żenczykowski *
511*1b481fc3SMaciej Żenczykowski * This function is similar to mnl_attr_put_str, but it includes the
512*1b481fc3SMaciej Żenczykowski * NUL/zero ('\0') terminator at the end of the string.
513*1b481fc3SMaciej Żenczykowski *
514*1b481fc3SMaciej Żenczykowski * This function updates the length field of the Netlink message (nlmsg_len)
515*1b481fc3SMaciej Żenczykowski * by adding the size (header + payload) of the new attribute.
516*1b481fc3SMaciej Żenczykowski */
mnl_attr_put_strz(struct nlmsghdr * nlh,uint16_t type,const char * data)517*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type,
518*1b481fc3SMaciej Żenczykowski const char *data)
519*1b481fc3SMaciej Żenczykowski {
520*1b481fc3SMaciej Żenczykowski mnl_attr_put(nlh, type, strlen(data)+1, data);
521*1b481fc3SMaciej Żenczykowski }
522*1b481fc3SMaciej Żenczykowski
523*1b481fc3SMaciej Żenczykowski /**
524*1b481fc3SMaciej Żenczykowski * mnl_attr_nest_start - start an attribute nest
525*1b481fc3SMaciej Żenczykowski * \param nlh pointer to the netlink message
526*1b481fc3SMaciej Żenczykowski * \param type netlink attribute type
527*1b481fc3SMaciej Żenczykowski *
528*1b481fc3SMaciej Żenczykowski * This function adds the attribute header that identifies the beginning of
529*1b481fc3SMaciej Żenczykowski * an attribute nest.
530*1b481fc3SMaciej Żenczykowski *
531*1b481fc3SMaciej Żenczykowski * \return valid pointer to the beginning of the nest
532*1b481fc3SMaciej Żenczykowski */
mnl_attr_nest_start(struct nlmsghdr * nlh,uint16_t type)533*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh,
534*1b481fc3SMaciej Żenczykowski uint16_t type)
535*1b481fc3SMaciej Żenczykowski {
536*1b481fc3SMaciej Żenczykowski struct nlattr *start = mnl_nlmsg_get_payload_tail(nlh);
537*1b481fc3SMaciej Żenczykowski
538*1b481fc3SMaciej Żenczykowski /* set start->nla_len in mnl_attr_nest_end() */
539*1b481fc3SMaciej Żenczykowski start->nla_type = NLA_F_NESTED | type;
540*1b481fc3SMaciej Żenczykowski nlh->nlmsg_len += MNL_ALIGN(sizeof(struct nlattr));
541*1b481fc3SMaciej Żenczykowski
542*1b481fc3SMaciej Żenczykowski return start;
543*1b481fc3SMaciej Żenczykowski }
544*1b481fc3SMaciej Żenczykowski
545*1b481fc3SMaciej Żenczykowski /**
546*1b481fc3SMaciej Żenczykowski * mnl_attr_put_check - add an attribute to netlink message
547*1b481fc3SMaciej Żenczykowski * \param nlh pointer to the netlink message
548*1b481fc3SMaciej Żenczykowski * \param buflen size of buffer which stores the message
549*1b481fc3SMaciej Żenczykowski * \param type netlink attribute type that you want to add
550*1b481fc3SMaciej Żenczykowski * \param len netlink attribute payload length
551*1b481fc3SMaciej Żenczykowski * \param data pointer to the data that will be stored by the new attribute
552*1b481fc3SMaciej Żenczykowski *
553*1b481fc3SMaciej Żenczykowski * This function first checks that the data can be added to the message
554*1b481fc3SMaciej Żenczykowski * (fits into the buffer) and then updates the length field of the Netlink
555*1b481fc3SMaciej Żenczykowski * message (nlmsg_len) by adding the size (header + payload) of the new
556*1b481fc3SMaciej Żenczykowski * attribute.
557*1b481fc3SMaciej Żenczykowski *
558*1b481fc3SMaciej Żenczykowski * \return true if the attribute could be added, false otherwise
559*1b481fc3SMaciej Żenczykowski */
mnl_attr_put_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type,size_t len,const void * data)560*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen,
561*1b481fc3SMaciej Żenczykowski uint16_t type, size_t len,
562*1b481fc3SMaciej Żenczykowski const void *data)
563*1b481fc3SMaciej Żenczykowski {
564*1b481fc3SMaciej Żenczykowski if (nlh->nlmsg_len + MNL_ATTR_HDRLEN + MNL_ALIGN(len) > buflen)
565*1b481fc3SMaciej Żenczykowski return false;
566*1b481fc3SMaciej Żenczykowski mnl_attr_put(nlh, type, len, data);
567*1b481fc3SMaciej Żenczykowski return true;
568*1b481fc3SMaciej Żenczykowski }
569*1b481fc3SMaciej Żenczykowski
570*1b481fc3SMaciej Żenczykowski /**
571*1b481fc3SMaciej Żenczykowski * mnl_attr_put_u8_check - add 8-bit unsigned int attribute to netlink message
572*1b481fc3SMaciej Żenczykowski * \param nlh pointer to the netlink message
573*1b481fc3SMaciej Żenczykowski * \param buflen size of buffer which stores the message
574*1b481fc3SMaciej Żenczykowski * \param type netlink attribute type
575*1b481fc3SMaciej Żenczykowski * \param data 8-bit unsigned integer data that is stored by the new attribute
576*1b481fc3SMaciej Żenczykowski *
577*1b481fc3SMaciej Żenczykowski * This function first checks that the data can be added to the message
578*1b481fc3SMaciej Żenczykowski * (fits into the buffer) and then updates the length field of the Netlink
579*1b481fc3SMaciej Żenczykowski * message (nlmsg_len) by adding the size (header + payload) of the new
580*1b481fc3SMaciej Żenczykowski * attribute.
581*1b481fc3SMaciej Żenczykowski *
582*1b481fc3SMaciej Żenczykowski * \return true if the attribute could be added, false otherwise
583*1b481fc3SMaciej Żenczykowski */
mnl_attr_put_u8_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type,uint8_t data)584*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen,
585*1b481fc3SMaciej Żenczykowski uint16_t type, uint8_t data)
586*1b481fc3SMaciej Żenczykowski {
587*1b481fc3SMaciej Żenczykowski return mnl_attr_put_check(nlh, buflen, type, sizeof(uint8_t), &data);
588*1b481fc3SMaciej Żenczykowski }
589*1b481fc3SMaciej Żenczykowski
590*1b481fc3SMaciej Żenczykowski /**
591*1b481fc3SMaciej Żenczykowski * mnl_attr_put_u16_check - add 16-bit unsigned int attribute to netlink message
592*1b481fc3SMaciej Żenczykowski * \param nlh pointer to the netlink message
593*1b481fc3SMaciej Żenczykowski * \param buflen size of buffer which stores the message
594*1b481fc3SMaciej Żenczykowski * \param type netlink attribute type
595*1b481fc3SMaciej Żenczykowski * \param data 16-bit unsigned integer data that is stored by the new attribute
596*1b481fc3SMaciej Żenczykowski *
597*1b481fc3SMaciej Żenczykowski * This function first checks that the data can be added to the message
598*1b481fc3SMaciej Żenczykowski * (fits into the buffer) and then updates the length field of the Netlink
599*1b481fc3SMaciej Żenczykowski * message (nlmsg_len) by adding the size (header + payload) of the new
600*1b481fc3SMaciej Żenczykowski * attribute.
601*1b481fc3SMaciej Żenczykowski *
602*1b481fc3SMaciej Żenczykowski * \return true if the attribute could be added, false otherwise
603*1b481fc3SMaciej Żenczykowski */
mnl_attr_put_u16_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type,uint16_t data)604*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen,
605*1b481fc3SMaciej Żenczykowski uint16_t type, uint16_t data)
606*1b481fc3SMaciej Żenczykowski {
607*1b481fc3SMaciej Żenczykowski return mnl_attr_put_check(nlh, buflen, type, sizeof(uint16_t), &data);
608*1b481fc3SMaciej Żenczykowski }
609*1b481fc3SMaciej Żenczykowski
610*1b481fc3SMaciej Żenczykowski /**
611*1b481fc3SMaciej Żenczykowski * mnl_attr_put_u32_check - add 32-bit unsigned int attribute to netlink message
612*1b481fc3SMaciej Żenczykowski * \param nlh pointer to the netlink message
613*1b481fc3SMaciej Żenczykowski * \param buflen size of buffer which stores the message
614*1b481fc3SMaciej Żenczykowski * \param type netlink attribute type
615*1b481fc3SMaciej Żenczykowski * \param data 32-bit unsigned integer data that is stored by the new attribute
616*1b481fc3SMaciej Żenczykowski *
617*1b481fc3SMaciej Żenczykowski * This function first checks that the data can be added to the message
618*1b481fc3SMaciej Żenczykowski * (fits into the buffer) and then updates the length field of the Netlink
619*1b481fc3SMaciej Żenczykowski * message (nlmsg_len) by adding the size (header + payload) of the new
620*1b481fc3SMaciej Żenczykowski * attribute.
621*1b481fc3SMaciej Żenczykowski *
622*1b481fc3SMaciej Żenczykowski * \return true if the attribute could be added, false otherwise
623*1b481fc3SMaciej Żenczykowski */
mnl_attr_put_u32_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type,uint32_t data)624*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen,
625*1b481fc3SMaciej Żenczykowski uint16_t type, uint32_t data)
626*1b481fc3SMaciej Żenczykowski {
627*1b481fc3SMaciej Żenczykowski return mnl_attr_put_check(nlh, buflen, type, sizeof(uint32_t), &data);
628*1b481fc3SMaciej Żenczykowski }
629*1b481fc3SMaciej Żenczykowski
630*1b481fc3SMaciej Żenczykowski /**
631*1b481fc3SMaciej Żenczykowski * mnl_attr_put_u64_check - add 64-bit unsigned int attribute to netlink message
632*1b481fc3SMaciej Żenczykowski * \param nlh pointer to the netlink message
633*1b481fc3SMaciej Żenczykowski * \param buflen size of buffer which stores the message
634*1b481fc3SMaciej Żenczykowski * \param type netlink attribute type
635*1b481fc3SMaciej Żenczykowski * \param data 64-bit unsigned integer data that is stored by the new attribute
636*1b481fc3SMaciej Żenczykowski *
637*1b481fc3SMaciej Żenczykowski * This function first checks that the data can be added to the message
638*1b481fc3SMaciej Żenczykowski * (fits into the buffer) and then updates the length field of the Netlink
639*1b481fc3SMaciej Żenczykowski * message (nlmsg_len) by adding the size (header + payload) of the new
640*1b481fc3SMaciej Żenczykowski * attribute.
641*1b481fc3SMaciej Żenczykowski *
642*1b481fc3SMaciej Żenczykowski * \return true if the attribute could be added, false otherwise
643*1b481fc3SMaciej Żenczykowski */
mnl_attr_put_u64_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type,uint64_t data)644*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL bool mnl_attr_put_u64_check(struct nlmsghdr *nlh, size_t buflen,
645*1b481fc3SMaciej Żenczykowski uint16_t type, uint64_t data)
646*1b481fc3SMaciej Żenczykowski {
647*1b481fc3SMaciej Żenczykowski return mnl_attr_put_check(nlh, buflen, type, sizeof(uint64_t), &data);
648*1b481fc3SMaciej Żenczykowski }
649*1b481fc3SMaciej Żenczykowski
650*1b481fc3SMaciej Żenczykowski /**
651*1b481fc3SMaciej Żenczykowski * mnl_attr_put_str_check - add string attribute to netlink message
652*1b481fc3SMaciej Żenczykowski * \param nlh pointer to the netlink message
653*1b481fc3SMaciej Żenczykowski * \param buflen size of buffer which stores the message
654*1b481fc3SMaciej Żenczykowski * \param type netlink attribute type
655*1b481fc3SMaciej Żenczykowski * \param data pointer to string data that is stored by the new attribute
656*1b481fc3SMaciej Żenczykowski *
657*1b481fc3SMaciej Żenczykowski * This function first checks that the data can be added to the message
658*1b481fc3SMaciej Żenczykowski * (fits into the buffer) and then updates the length field of the Netlink
659*1b481fc3SMaciej Żenczykowski * message (nlmsg_len) by adding the size (header + payload) of the new
660*1b481fc3SMaciej Żenczykowski * attribute.
661*1b481fc3SMaciej Żenczykowski *
662*1b481fc3SMaciej Żenczykowski * \return true if the attribute could be added, false otherwise
663*1b481fc3SMaciej Żenczykowski */
mnl_attr_put_str_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type,const char * data)664*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL bool mnl_attr_put_str_check(struct nlmsghdr *nlh, size_t buflen,
665*1b481fc3SMaciej Żenczykowski uint16_t type, const char *data)
666*1b481fc3SMaciej Żenczykowski {
667*1b481fc3SMaciej Żenczykowski return mnl_attr_put_check(nlh, buflen, type, strlen(data), data);
668*1b481fc3SMaciej Żenczykowski }
669*1b481fc3SMaciej Żenczykowski
670*1b481fc3SMaciej Żenczykowski /**
671*1b481fc3SMaciej Żenczykowski * mnl_attr_put_strz_check - add string attribute to netlink message
672*1b481fc3SMaciej Żenczykowski * \param nlh pointer to the netlink message
673*1b481fc3SMaciej Żenczykowski * \param buflen size of buffer which stores the message
674*1b481fc3SMaciej Żenczykowski * \param type netlink attribute type
675*1b481fc3SMaciej Żenczykowski * \param data pointer to string data that is stored by the new attribute
676*1b481fc3SMaciej Żenczykowski *
677*1b481fc3SMaciej Żenczykowski * This function is similar to mnl_attr_put_str, but it includes the
678*1b481fc3SMaciej Żenczykowski * NUL/zero ('\0') terminator at the end of the string.
679*1b481fc3SMaciej Żenczykowski *
680*1b481fc3SMaciej Żenczykowski * This function first checks that the data can be added to the message
681*1b481fc3SMaciej Żenczykowski * (fits into the buffer) and then updates the length field of the Netlink
682*1b481fc3SMaciej Żenczykowski * message (nlmsg_len) by adding the size (header + payload) of the new
683*1b481fc3SMaciej Żenczykowski * attribute.
684*1b481fc3SMaciej Żenczykowski *
685*1b481fc3SMaciej Żenczykowski * \return true if the attribute could be added, false otherwise
686*1b481fc3SMaciej Żenczykowski */
mnl_attr_put_strz_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type,const char * data)687*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL bool mnl_attr_put_strz_check(struct nlmsghdr *nlh, size_t buflen,
688*1b481fc3SMaciej Żenczykowski uint16_t type, const char *data)
689*1b481fc3SMaciej Żenczykowski {
690*1b481fc3SMaciej Żenczykowski return mnl_attr_put_check(nlh, buflen, type, strlen(data)+1, data);
691*1b481fc3SMaciej Żenczykowski }
692*1b481fc3SMaciej Żenczykowski
693*1b481fc3SMaciej Żenczykowski /**
694*1b481fc3SMaciej Żenczykowski * mnl_attr_nest_start_check - start an attribute nest
695*1b481fc3SMaciej Żenczykowski * \param buflen size of buffer which stores the message
696*1b481fc3SMaciej Żenczykowski * \param nlh pointer to the netlink message
697*1b481fc3SMaciej Żenczykowski * \param type netlink attribute type
698*1b481fc3SMaciej Żenczykowski *
699*1b481fc3SMaciej Żenczykowski * This function adds the attribute header that identifies the beginning of
700*1b481fc3SMaciej Żenczykowski * an attribute nest.
701*1b481fc3SMaciej Żenczykowski *
702*1b481fc3SMaciej Żenczykowski * \return NULL if the attribute cannot be added, otherwise a pointer to the
703*1b481fc3SMaciej Żenczykowski * beginning of the nest
704*1b481fc3SMaciej Żenczykowski */
mnl_attr_nest_start_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type)705*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL struct nlattr *mnl_attr_nest_start_check(struct nlmsghdr *nlh,
706*1b481fc3SMaciej Żenczykowski size_t buflen,
707*1b481fc3SMaciej Żenczykowski uint16_t type)
708*1b481fc3SMaciej Żenczykowski {
709*1b481fc3SMaciej Żenczykowski if (nlh->nlmsg_len + MNL_ATTR_HDRLEN > buflen)
710*1b481fc3SMaciej Żenczykowski return NULL;
711*1b481fc3SMaciej Żenczykowski return mnl_attr_nest_start(nlh, type);
712*1b481fc3SMaciej Żenczykowski }
713*1b481fc3SMaciej Żenczykowski
714*1b481fc3SMaciej Żenczykowski /**
715*1b481fc3SMaciej Żenczykowski * mnl_attr_nest_end - end an attribute nest
716*1b481fc3SMaciej Żenczykowski * \param nlh pointer to the netlink message
717*1b481fc3SMaciej Żenczykowski * \param start pointer to the attribute nest returned by mnl_attr_nest_start()
718*1b481fc3SMaciej Żenczykowski *
719*1b481fc3SMaciej Żenczykowski * This function updates the attribute header that identifies the nest.
720*1b481fc3SMaciej Żenczykowski */
mnl_attr_nest_end(struct nlmsghdr * nlh,struct nlattr * start)721*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL void mnl_attr_nest_end(struct nlmsghdr *nlh,
722*1b481fc3SMaciej Żenczykowski struct nlattr *start)
723*1b481fc3SMaciej Żenczykowski {
724*1b481fc3SMaciej Żenczykowski start->nla_len = mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
725*1b481fc3SMaciej Żenczykowski }
726*1b481fc3SMaciej Żenczykowski
727*1b481fc3SMaciej Żenczykowski /**
728*1b481fc3SMaciej Żenczykowski * mnl_attr_nest_cancel - cancel an attribute nest
729*1b481fc3SMaciej Żenczykowski * \param nlh pointer to the netlink message
730*1b481fc3SMaciej Żenczykowski * \param start pointer to the attribute nest returned by mnl_attr_nest_start()
731*1b481fc3SMaciej Żenczykowski *
732*1b481fc3SMaciej Żenczykowski * This function updates the attribute header that identifies the nest.
733*1b481fc3SMaciej Żenczykowski */
mnl_attr_nest_cancel(struct nlmsghdr * nlh,struct nlattr * start)734*1b481fc3SMaciej Żenczykowski EXPORT_SYMBOL void mnl_attr_nest_cancel(struct nlmsghdr *nlh,
735*1b481fc3SMaciej Żenczykowski struct nlattr *start)
736*1b481fc3SMaciej Żenczykowski {
737*1b481fc3SMaciej Żenczykowski nlh->nlmsg_len -= mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
738*1b481fc3SMaciej Żenczykowski }
739*1b481fc3SMaciej Żenczykowski
740*1b481fc3SMaciej Żenczykowski /**
741*1b481fc3SMaciej Żenczykowski * @}
742*1b481fc3SMaciej Żenczykowski */
743