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