1 /*
2 * (C) 2008-2012 by Pablo Neira Ayuso <pablo@netfilter.org>
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_uint - returns 64-bit unsigned integer attribute.
394 * \param attr pointer to netlink attribute
395 *
396 * This helper function reads the variable-length netlink attribute NLA_UINT
397 * that provides a 32-bit or 64-bit integer payload. Its use is recommended only
398 * in these cases.
399 *
400 * Recommended validation for NLA_UINT is:
401 *
402 * \verbatim
403 if (!mnl_attr_validate(attr, NLA_U32) &&
404 !mnl_attr_validate(attr, NLA_U64)) {
405 perror("mnl_attr_validate");
406 return MNL_CB_ERROR;
407 }
408 \endverbatim
409 *
410 * \returns the 64-bit value of the attribute payload. On error, it returns
411 * UINT64_MAX if the length of the netlink attribute is not an 8-bit, 16-bit,
412 * 32-bit and 64-bit integer. Therefore, there is no way to distinguish between
413 * UINT64_MAX and an error. Also, errno is never set.
414 */
mnl_attr_get_uint(const struct nlattr * attr)415 EXPORT_SYMBOL uint64_t mnl_attr_get_uint(const struct nlattr *attr)
416 {
417 switch (mnl_attr_get_payload_len(attr)) {
418 case sizeof(uint8_t):
419 return mnl_attr_get_u8(attr);
420 case sizeof(uint16_t):
421 return mnl_attr_get_u16(attr);
422 case sizeof(uint32_t):
423 return mnl_attr_get_u32(attr);
424 case sizeof(uint64_t):
425 return mnl_attr_get_u64(attr);
426 }
427
428 return -1ULL;
429 }
430
431 /**
432 * mnl_attr_get_str - get pointer to string attribute
433 * \param attr pointer to netlink attribute
434 *
435 * \return string pointer of the attribute payload
436 */
mnl_attr_get_str(const struct nlattr * attr)437 EXPORT_SYMBOL const char *mnl_attr_get_str(const struct nlattr *attr)
438 {
439 return mnl_attr_get_payload(attr);
440 }
441
442 /**
443 * mnl_attr_put - add an attribute to netlink message
444 * \param nlh pointer to the netlink message
445 * \param type netlink attribute type that you want to add
446 * \param len netlink attribute payload length
447 * \param data pointer to the data that will be stored by the new attribute
448 *
449 * This function updates the length field of the Netlink message (nlmsg_len)
450 * by adding the size (header + payload) of the new attribute.
451 */
mnl_attr_put(struct nlmsghdr * nlh,uint16_t type,size_t len,const void * data)452 EXPORT_SYMBOL void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type,
453 size_t len, const void *data)
454 {
455 struct nlattr *attr = mnl_nlmsg_get_payload_tail(nlh);
456 uint16_t payload_len = MNL_ALIGN(sizeof(struct nlattr)) + len;
457 int pad;
458
459 attr->nla_type = type;
460 attr->nla_len = payload_len;
461 memcpy(mnl_attr_get_payload(attr), data, len);
462 pad = MNL_ALIGN(len) - len;
463 if (pad > 0)
464 memset(mnl_attr_get_payload(attr) + len, 0, pad);
465
466 nlh->nlmsg_len += MNL_ALIGN(payload_len);
467 }
468
469 /**
470 * mnl_attr_put_u8 - add 8-bit unsigned integer attribute to netlink message
471 * \param nlh pointer to the netlink message
472 * \param type netlink attribute type
473 * \param data 8-bit unsigned integer data that is stored by the new attribute
474 *
475 * This function updates the length field of the Netlink message (nlmsg_len)
476 * by adding the size (header + payload) of the new attribute.
477 */
mnl_attr_put_u8(struct nlmsghdr * nlh,uint16_t type,uint8_t data)478 EXPORT_SYMBOL void mnl_attr_put_u8(struct nlmsghdr *nlh, uint16_t type,
479 uint8_t data)
480 {
481 mnl_attr_put(nlh, type, sizeof(uint8_t), &data);
482 }
483
484 /**
485 * mnl_attr_put_u16 - add 16-bit unsigned integer attribute to netlink message
486 * \param nlh pointer to the netlink message
487 * \param type netlink attribute type
488 * \param data 16-bit unsigned integer data that is stored by the new attribute
489 *
490 * This function updates the length field of the Netlink message (nlmsg_len)
491 * by adding the size (header + payload) of the new attribute.
492 */
mnl_attr_put_u16(struct nlmsghdr * nlh,uint16_t type,uint16_t data)493 EXPORT_SYMBOL void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type,
494 uint16_t data)
495 {
496 mnl_attr_put(nlh, type, sizeof(uint16_t), &data);
497 }
498
499 /**
500 * mnl_attr_put_u32 - add 32-bit unsigned integer attribute to netlink message
501 * \param nlh pointer to the netlink message
502 * \param type netlink attribute type
503 * \param data 32-bit unsigned integer data that is stored by the new attribute
504 *
505 * This function updates the length field of the Netlink message (nlmsg_len)
506 * by adding the size (header + payload) of the new attribute.
507 */
mnl_attr_put_u32(struct nlmsghdr * nlh,uint16_t type,uint32_t data)508 EXPORT_SYMBOL void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type,
509 uint32_t data)
510 {
511 mnl_attr_put(nlh, type, sizeof(uint32_t), &data);
512 }
513
514 /**
515 * mnl_attr_put_u64 - add 64-bit unsigned integer attribute to netlink message
516 * \param nlh pointer to the netlink message
517 * \param type netlink attribute type
518 * \param data 64-bit unsigned integer data that is stored by the new attribute
519 *
520 * This function updates the length field of the Netlink message (nlmsg_len)
521 * by adding the size (header + payload) of the new attribute.
522 */
mnl_attr_put_u64(struct nlmsghdr * nlh,uint16_t type,uint64_t data)523 EXPORT_SYMBOL void mnl_attr_put_u64(struct nlmsghdr *nlh, uint16_t type,
524 uint64_t data)
525 {
526 mnl_attr_put(nlh, type, sizeof(uint64_t), &data);
527 }
528
529 /**
530 * mnl_attr_put_str - add string attribute to netlink message
531 * \param nlh pointer to the netlink message
532 * \param type netlink attribute type
533 * \param data pointer to string data that is stored by the new attribute
534 *
535 * This function updates the length field of the Netlink message (nlmsg_len)
536 * by adding the size (header + payload) of the new attribute.
537 */
mnl_attr_put_str(struct nlmsghdr * nlh,uint16_t type,const char * data)538 EXPORT_SYMBOL void mnl_attr_put_str(struct nlmsghdr *nlh, uint16_t type,
539 const char *data)
540 {
541 mnl_attr_put(nlh, type, strlen(data), data);
542 }
543
544 /**
545 * mnl_attr_put_strz - add string attribute to netlink message
546 * \param nlh pointer to the netlink message
547 * \param type netlink attribute type
548 * \param data pointer to string data that is stored by the new attribute
549 *
550 * This function is similar to mnl_attr_put_str, but it includes the
551 * NUL/zero ('\0') terminator at the end of the string.
552 *
553 * This function updates the length field of the Netlink message (nlmsg_len)
554 * by adding the size (header + payload) of the new attribute.
555 */
mnl_attr_put_strz(struct nlmsghdr * nlh,uint16_t type,const char * data)556 EXPORT_SYMBOL void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type,
557 const char *data)
558 {
559 mnl_attr_put(nlh, type, strlen(data)+1, data);
560 }
561
562 /**
563 * mnl_attr_nest_start - start an attribute nest
564 * \param nlh pointer to the netlink message
565 * \param type netlink attribute type
566 *
567 * This function adds the attribute header that identifies the beginning of
568 * an attribute nest.
569 *
570 * \return valid pointer to the beginning of the nest
571 */
mnl_attr_nest_start(struct nlmsghdr * nlh,uint16_t type)572 EXPORT_SYMBOL struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh,
573 uint16_t type)
574 {
575 struct nlattr *start = mnl_nlmsg_get_payload_tail(nlh);
576
577 /* set start->nla_len in mnl_attr_nest_end() */
578 start->nla_type = NLA_F_NESTED | type;
579 nlh->nlmsg_len += MNL_ALIGN(sizeof(struct nlattr));
580
581 return start;
582 }
583
584 /**
585 * mnl_attr_put_check - add an attribute to netlink message
586 * \param nlh pointer to the netlink message
587 * \param buflen size of buffer which stores the message
588 * \param type netlink attribute type that you want to add
589 * \param len netlink attribute payload length
590 * \param data pointer to the data that will be stored by the new attribute
591 *
592 * This function first checks that the data can be added to the message
593 * (fits into the buffer) and then updates the length field of the Netlink
594 * message (nlmsg_len) by adding the size (header + payload) of the new
595 * attribute.
596 *
597 * \return true if the attribute could be added, false otherwise
598 */
mnl_attr_put_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type,size_t len,const void * data)599 EXPORT_SYMBOL bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen,
600 uint16_t type, size_t len,
601 const void *data)
602 {
603 if (nlh->nlmsg_len + MNL_ATTR_HDRLEN + MNL_ALIGN(len) > buflen)
604 return false;
605 mnl_attr_put(nlh, type, len, data);
606 return true;
607 }
608
609 /**
610 * mnl_attr_put_u8_check - add 8-bit unsigned int attribute to netlink message
611 * \param nlh pointer to the netlink message
612 * \param buflen size of buffer which stores the message
613 * \param type netlink attribute type
614 * \param data 8-bit unsigned integer data that is stored by the new attribute
615 *
616 * This function first checks that the data can be added to the message
617 * (fits into the buffer) and then updates the length field of the Netlink
618 * message (nlmsg_len) by adding the size (header + payload) of the new
619 * attribute.
620 *
621 * \return true if the attribute could be added, false otherwise
622 */
mnl_attr_put_u8_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type,uint8_t data)623 EXPORT_SYMBOL bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen,
624 uint16_t type, uint8_t data)
625 {
626 return mnl_attr_put_check(nlh, buflen, type, sizeof(uint8_t), &data);
627 }
628
629 /**
630 * mnl_attr_put_u16_check - add 16-bit unsigned int attribute to netlink message
631 * \param nlh pointer to the netlink message
632 * \param buflen size of buffer which stores the message
633 * \param type netlink attribute type
634 * \param data 16-bit unsigned integer data that is stored by the new attribute
635 *
636 * This function first checks that the data can be added to the message
637 * (fits into the buffer) and then updates the length field of the Netlink
638 * message (nlmsg_len) by adding the size (header + payload) of the new
639 * attribute.
640 *
641 * \return true if the attribute could be added, false otherwise
642 */
mnl_attr_put_u16_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type,uint16_t data)643 EXPORT_SYMBOL bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen,
644 uint16_t type, uint16_t data)
645 {
646 return mnl_attr_put_check(nlh, buflen, type, sizeof(uint16_t), &data);
647 }
648
649 /**
650 * mnl_attr_put_u32_check - add 32-bit unsigned int attribute to netlink message
651 * \param nlh pointer to the netlink message
652 * \param buflen size of buffer which stores the message
653 * \param type netlink attribute type
654 * \param data 32-bit unsigned integer data that is stored by the new attribute
655 *
656 * This function first checks that the data can be added to the message
657 * (fits into the buffer) and then updates the length field of the Netlink
658 * message (nlmsg_len) by adding the size (header + payload) of the new
659 * attribute.
660 *
661 * \return true if the attribute could be added, false otherwise
662 */
mnl_attr_put_u32_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type,uint32_t data)663 EXPORT_SYMBOL bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen,
664 uint16_t type, uint32_t data)
665 {
666 return mnl_attr_put_check(nlh, buflen, type, sizeof(uint32_t), &data);
667 }
668
669 /**
670 * mnl_attr_put_u64_check - add 64-bit unsigned int attribute to netlink message
671 * \param nlh pointer to the netlink message
672 * \param buflen size of buffer which stores the message
673 * \param type netlink attribute type
674 * \param data 64-bit unsigned integer data that is stored by the new attribute
675 *
676 * This function first checks that the data can be added to the message
677 * (fits into the buffer) and then updates the length field of the Netlink
678 * message (nlmsg_len) by adding the size (header + payload) of the new
679 * attribute.
680 *
681 * \return true if the attribute could be added, false otherwise
682 */
mnl_attr_put_u64_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type,uint64_t data)683 EXPORT_SYMBOL bool mnl_attr_put_u64_check(struct nlmsghdr *nlh, size_t buflen,
684 uint16_t type, uint64_t data)
685 {
686 return mnl_attr_put_check(nlh, buflen, type, sizeof(uint64_t), &data);
687 }
688
689 /**
690 * mnl_attr_put_str_check - add string attribute to netlink message
691 * \param nlh pointer to the netlink message
692 * \param buflen size of buffer which stores the message
693 * \param type netlink attribute type
694 * \param data pointer to string data that is stored by the new attribute
695 *
696 * This function first checks that the data can be added to the message
697 * (fits into the buffer) and then updates the length field of the Netlink
698 * message (nlmsg_len) by adding the size (header + payload) of the new
699 * attribute.
700 *
701 * \return true if the attribute could be added, false otherwise
702 */
mnl_attr_put_str_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type,const char * data)703 EXPORT_SYMBOL bool mnl_attr_put_str_check(struct nlmsghdr *nlh, size_t buflen,
704 uint16_t type, const char *data)
705 {
706 return mnl_attr_put_check(nlh, buflen, type, strlen(data), data);
707 }
708
709 /**
710 * mnl_attr_put_strz_check - add string attribute to netlink message
711 * \param nlh pointer to the netlink message
712 * \param buflen size of buffer which stores the message
713 * \param type netlink attribute type
714 * \param data pointer to string data that is stored by the new attribute
715 *
716 * This function is similar to mnl_attr_put_str, but it includes the
717 * NUL/zero ('\0') terminator at the end of the string.
718 *
719 * This function first checks that the data can be added to the message
720 * (fits into the buffer) and then updates the length field of the Netlink
721 * message (nlmsg_len) by adding the size (header + payload) of the new
722 * attribute.
723 *
724 * \return true if the attribute could be added, false otherwise
725 */
mnl_attr_put_strz_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type,const char * data)726 EXPORT_SYMBOL bool mnl_attr_put_strz_check(struct nlmsghdr *nlh, size_t buflen,
727 uint16_t type, const char *data)
728 {
729 return mnl_attr_put_check(nlh, buflen, type, strlen(data)+1, data);
730 }
731
732 /**
733 * mnl_attr_nest_start_check - start an attribute nest
734 * \param buflen size of buffer which stores the message
735 * \param nlh pointer to the netlink message
736 * \param type netlink attribute type
737 *
738 * This function adds the attribute header that identifies the beginning of
739 * an attribute nest.
740 *
741 * \return NULL if the attribute cannot be added, otherwise a pointer to the
742 * beginning of the nest
743 */
mnl_attr_nest_start_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type)744 EXPORT_SYMBOL struct nlattr *mnl_attr_nest_start_check(struct nlmsghdr *nlh,
745 size_t buflen,
746 uint16_t type)
747 {
748 if (nlh->nlmsg_len + MNL_ATTR_HDRLEN > buflen)
749 return NULL;
750 return mnl_attr_nest_start(nlh, type);
751 }
752
753 /**
754 * mnl_attr_nest_end - end an attribute nest
755 * \param nlh pointer to the netlink message
756 * \param start pointer to the attribute nest returned by mnl_attr_nest_start()
757 *
758 * This function updates the attribute header that identifies the nest.
759 */
mnl_attr_nest_end(struct nlmsghdr * nlh,struct nlattr * start)760 EXPORT_SYMBOL void mnl_attr_nest_end(struct nlmsghdr *nlh,
761 struct nlattr *start)
762 {
763 start->nla_len = mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
764 }
765
766 /**
767 * mnl_attr_nest_cancel - cancel an attribute nest
768 * \param nlh pointer to the netlink message
769 * \param start pointer to the attribute nest returned by mnl_attr_nest_start()
770 *
771 * This function updates the attribute header that identifies the nest.
772 */
mnl_attr_nest_cancel(struct nlmsghdr * nlh,struct nlattr * start)773 EXPORT_SYMBOL void mnl_attr_nest_cancel(struct nlmsghdr *nlh,
774 struct nlattr *start)
775 {
776 nlh->nlmsg_len -= mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
777 }
778
779 /**
780 * @}
781 */
782