libnl 3.10.0
attr.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
4 */
5
6#include "nl-default.h"
7
8#include <linux/socket.h>
9
10#include <netlink/netlink.h>
11#include <netlink/utils.h>
12#include <netlink/addr.h>
13#include <netlink/attr.h>
14#include <netlink/msg.h>
15
16#include "nl-priv-dynamic-core/nl-core.h"
17#include "nl-aux-core/nl-core.h"
18
19/**
20 * @ingroup msg
21 * @defgroup attr Attributes
22 * Netlink Attributes Construction/Parsing Interface
23 *
24 * Related sections in the development guide:
25 * - @core_doc{core_attr,Netlink Attributes}
26 *
27 * @{
28 *
29 * Header
30 * ------
31 * ~~~~{.c}
32 * #include <netlink/attr.h>
33 * ~~~~
34 */
35
36/**
37 * @name Attribute Size Calculation
38 * @{
39 */
40
41/**
42 * Return size of attribute whithout padding.
43 * @arg payload Payload length of attribute.
44 *
45 * @code
46 * <-------- nla_attr_size(payload) --------->
47 * +------------------+- - -+- - - - - - - - - +- - -+
48 * | Attribute Header | Pad | Payload | Pad |
49 * +------------------+- - -+- - - - - - - - - +- - -+
50 * @endcode
51 *
52 * @return Size of attribute in bytes without padding.
53 */
54int nla_attr_size(int payload)
55{
56 return NLA_HDRLEN + payload;
57}
58
59/**
60 * Return size of attribute including padding.
61 * @arg payload Payload length of attribute.
62 *
63 * @code
64 * <----------- nla_total_size(payload) ----------->
65 * +------------------+- - -+- - - - - - - - - +- - -+
66 * | Attribute Header | Pad | Payload | Pad |
67 * +------------------+- - -+- - - - - - - - - +- - -+
68 * @endcode
69 *
70 * @return Size of attribute in bytes.
71 */
72int nla_total_size(int payload)
73{
74 return NLA_ALIGN(nla_attr_size(payload));
75}
76
77/**
78 * Return length of padding at the tail of the attribute.
79 * @arg payload Payload length of attribute.
80 *
81 * @code
82 * +------------------+- - -+- - - - - - - - - +- - -+
83 * | Attribute Header | Pad | Payload | Pad |
84 * +------------------+- - -+- - - - - - - - - +- - -+
85 * <--->
86 * @endcode
87 *
88 * @return Length of padding in bytes.
89 */
90int nla_padlen(int payload)
91{
92 return nla_total_size(payload) - nla_attr_size(payload);
93}
94
95/** @} */
96
97/**
98 * @name Parsing Attributes
99 * @{
100 */
101
102/**
103 * Return type of the attribute.
104 * @arg nla Attribute.
105 *
106 * @return Type of attribute.
107 */
108int nla_type(const struct nlattr *nla)
109{
110 return nla->nla_type & NLA_TYPE_MASK;
111}
112
113/**
114 * Return pointer to the payload section.
115 * @arg nla Attribute.
116 *
117 * @return Pointer to start of payload section.
118 */
119void *nla_data(const struct nlattr *nla)
120{
121 return (char *) nla + NLA_HDRLEN;
122}
123
124/**
125 * Return length of the payload .
126 * @arg nla Attribute
127 *
128 * @return Length of payload in bytes.
129 */
130int nla_len(const struct nlattr *nla)
131{
132 return _nla_len(nla);
133}
134
135/**
136 * Check if the attribute header and payload can be accessed safely.
137 * @arg nla Attribute of any kind.
138 * @arg remaining Number of bytes remaining in attribute stream.
139 *
140 * Verifies that the header and payload do not exceed the number of
141 * bytes left in the attribute stream. This function must be called
142 * before access the attribute header or payload when iterating over
143 * the attribute stream using nla_next().
144 *
145 * @return True if the attribute can be accessed safely, false otherwise.
146 */
147int nla_ok(const struct nlattr *nla, int remaining)
148{
149 _NL_STATIC_ASSERT(sizeof(*nla) == NLA_HDRLEN);
150
151 return remaining >= (int) sizeof(*nla) &&
152 nla->nla_len >= sizeof(*nla) &&
153 nla->nla_len <= remaining;
154}
155
156/**
157 * Return next attribute in a stream of attributes.
158 * @arg nla Attribute of any kind.
159 * @arg remaining Variable to count remaining bytes in stream.
160 *
161 * Calculates the offset to the next attribute based on the attribute
162 * given. The attribute provided is assumed to be accessible, the
163 * caller is responsible to use nla_ok() beforehand. The offset (length
164 * of specified attribute including padding) is then subtracted from
165 * the remaining bytes variable and a pointer to the next attribute is
166 * returned.
167 *
168 * nla_next() can be called as long as remainig is >0.
169 *
170 * @return Pointer to next attribute.
171 */
172struct nlattr *nla_next(const struct nlattr *nla, int *remaining)
173{
174 int totlen = NLA_ALIGN(nla->nla_len);
175
176 *remaining -= totlen;
177 return (struct nlattr *) ((char *) nla + totlen);
178}
179
180static uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = {
181 [NLA_U8] = sizeof(uint8_t),
182 [NLA_U16] = sizeof(uint16_t),
183 [NLA_U32] = sizeof(uint32_t),
184 [NLA_U64] = sizeof(uint64_t),
185 [NLA_STRING] = 1,
186 [NLA_FLAG] = 0,
187};
188
189static int validate_nla(const struct nlattr *nla, int maxtype,
190 const struct nla_policy *policy)
191{
192 const struct nla_policy *pt;
193 unsigned int minlen = 0;
194 int type = nla_type(nla);
195
197 return 0;
198
199 pt = &policy[type];
200
201 if (pt->type > NLA_TYPE_MAX)
202 BUG();
203
204 if (pt->minlen)
205 minlen = pt->minlen;
206 else if (pt->type != NLA_UNSPEC)
207 minlen = nla_attr_minlen[pt->type];
208
209 if (_nla_len(nla) < minlen)
210 return -NLE_RANGE;
211
212 if (pt->maxlen && nla_len(nla) > pt->maxlen)
213 return -NLE_RANGE;
214
215 if (pt->type == NLA_STRING) {
216 const char *data = nla_data(nla);
217 if (data[nla_len(nla) - 1] != '\0')
218 return -NLE_INVAL;
219 }
220
221 return 0;
222}
223
224
225/**
226 * Create attribute index based on a stream of attributes.
227 * @arg tb Index array to be filled (maxtype+1 elements).
228 * @arg maxtype Maximum attribute type expected and accepted.
229 * @arg head Head of attribute stream.
230 * @arg len Length of attribute stream.
231 * @arg policy Attribute validation policy.
232 *
233 * Iterates over the stream of attributes and stores a pointer to each
234 * attribute in the index array using the attribute type as index to
235 * the array. Attribute with a type greater than the maximum type
236 * specified will be silently ignored in order to maintain backwards
237 * compatibility. If \a policy is not NULL, the attribute will be
238 * validated using the specified policy.
239 *
240 * @see nla_validate
241 * @return 0 on success or a negative error code.
242 */
243int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
244 const struct nla_policy *policy)
245{
246 struct nlattr *nla;
247 int rem, err;
248
249 memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
250
251 nla_for_each_attr(nla, head, len, rem) {
252 int type = nla_type(nla);
253
254 if (type > maxtype)
255 continue;
256
257 if (policy) {
258 err = validate_nla(nla, maxtype, policy);
259 if (err < 0)
260 return err;
261 }
262
263 if (tb[type])
264 NL_DBG(1, "Attribute of type %#x found multiple times in message, "
265 "previous attribute is being ignored.\n", type);
266
267 tb[type] = nla;
268 }
269
270 if (rem > 0) {
271 NL_DBG(1, "netlink: %d bytes leftover after parsing "
272 "attributes.\n", rem);
273 }
274
275 return 0;
276}
277
278/**
279 * Validate a stream of attributes.
280 * @arg head Head of attributes stream.
281 * @arg len Length of attributes stream.
282 * @arg maxtype Maximum attribute type expected and accepted.
283 * @arg policy Validation policy.
284 *
285 * Iterates over the stream of attributes and validates each attribute
286 * one by one using the specified policy. Attributes with a type greater
287 * than the maximum type specified will be silently ignored in order to
288 * maintain backwards compatibility.
289 *
290 * See section @core_doc{core_attr_parse,Attribute Parsing} for more details.
291 *
292 * @return 0 on success or a negative error code.
293 */
294int nla_validate(const struct nlattr *head, int len, int maxtype,
295 const struct nla_policy *policy)
296{
297 const struct nlattr *nla;
298 int rem, err;
299
300 nla_for_each_attr(nla, head, len, rem) {
301 err = validate_nla(nla, maxtype, policy);
302 if (err < 0)
303 goto errout;
304 }
305
306 err = 0;
307errout:
308 return err;
309}
310
311/**
312 * Find a single attribute in a stream of attributes.
313 * @arg head Head of attributes stream.
314 * @arg len Length of attributes stream.
315 * @arg attrtype Attribute type to look for.
316 *
317 * Iterates over the stream of attributes and compares each type with
318 * the type specified. Returns the first attribute which matches the
319 * type.
320 *
321 * @return Pointer to attribute found or NULL.
322 */
323struct nlattr *nla_find(const struct nlattr *head, int len, int attrtype)
324{
325 const struct nlattr *nla;
326 int rem;
327
328 nla_for_each_attr(nla, head, len, rem)
329 if (nla_type(nla) == attrtype)
330 return (struct nlattr*)nla;
331
332 return NULL;
333}
334
335/** @} */
336
337/**
338 * @name Helper Functions
339 * @{
340 */
341
342/**
343 * Copy attribute payload to another memory area.
344 * @arg dest Pointer to destination memory area.
345 * @arg src Attribute
346 * @arg count Number of bytes to copy at most.
347 *
348 * Note: The number of bytes copied is limited by the length of
349 * the attribute payload.
350 *
351 * @return The number of bytes copied to dest.
352 */
353int nla_memcpy(void *dest, const struct nlattr *src, int count)
354{
355 int minlen;
356
357 if (!src)
358 return 0;
359
360 minlen = _NL_MIN(count, nla_len(src));
361
362 if (minlen <= 0)
363 return 0;
364
365 memcpy(dest, nla_data(src), minlen);
366 return minlen;
367}
368
369/**
370 * Copy string attribute payload to a buffer.
371 * @arg dst Pointer to destination buffer.
372 * @arg nla Attribute of type NLA_STRING.
373 * @arg dstsize Size of destination buffer in bytes.
374 *
375 * Copies at most dstsize - 1 bytes to the destination buffer.
376 * The result is always a valid NUL terminated string. Unlike
377 * strlcpy the destination buffer is always padded out.
378 *
379 * @return The length of string attribute without the terminating NUL.
380 */
381size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
382{
383 size_t srclen = nla_len(nla);
384 const char *src = nla_data(nla);
385
386 if (srclen > 0 && src[srclen - 1] == '\0')
387 srclen--;
388
389 if (dstsize > 0) {
390 size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
391
392 memset(dst, 0, dstsize);
393 memcpy(dst, src, len);
394 }
395
396 return srclen;
397}
398
399/**
400 * Compare attribute payload with memory area.
401 * @arg nla Attribute.
402 * @arg data Memory area to compare to.
403 * @arg size Number of bytes to compare.
404 *
405 * @see memcmp(3)
406 * @return An integer less than, equal to, or greater than zero.
407 */
408int nla_memcmp(const struct nlattr *nla, const void *data, size_t size)
409{
410 int d = nla_len(nla) - size;
411
412 if (d == 0)
413 d = memcmp(nla_data(nla), data, size);
414
415 return d;
416}
417
418/**
419 * Compare string attribute payload with string
420 * @arg nla Attribute of type NLA_STRING.
421 * @arg str NUL terminated string.
422 *
423 * @see strcmp(3)
424 * @return An integer less than, equal to, or greater than zero.
425 */
426int nla_strcmp(const struct nlattr *nla, const char *str)
427{
428 int len = strlen(str) + 1;
429 int d = nla_len(nla) - len;
430
431 if (d == 0)
432 d = memcmp(nla_data(nla), str, len);
433
434 return d;
435}
436
437/** @} */
438
439/**
440 * @name Unspecific Attribute
441 * @{
442 */
443
444/**
445 * Reserve space for a attribute.
446 * @arg msg Netlink Message.
447 * @arg attrtype Attribute Type.
448 * @arg attrlen Length of payload.
449 *
450 * Reserves room for a attribute in the specified netlink message and
451 * fills in the attribute header (type, length). Returns NULL if there
452 * is unsuficient space for the attribute.
453 *
454 * Any padding between payload and the start of the next attribute is
455 * zeroed out.
456 *
457 * @return Pointer to start of attribute or NULL on failure.
458 */
459struct nlattr *nla_reserve(struct nl_msg *msg, int attrtype, int attrlen)
460{
461 struct nlattr *nla;
462 size_t tlen;
463
464 if (attrlen < 0)
465 return NULL;
466
467 tlen = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) + nla_total_size(attrlen);
468
469 if (tlen > msg->nm_size || tlen > UINT32_MAX)
470 return NULL;
471
472 nla = (struct nlattr *) nlmsg_tail(msg->nm_nlh);
473 nla->nla_type = attrtype;
474 nla->nla_len = nla_attr_size(attrlen);
475
476 if (attrlen)
477 memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen));
478 msg->nm_nlh->nlmsg_len = tlen;
479
480 NL_DBG(2, "msg %p: attr <%p> %d: Reserved %d (%d) bytes at offset +%td "
481 "nlmsg_len=%d\n", msg, nla, nla->nla_type,
482 nla_total_size(attrlen), attrlen,
483 (char *) nla - (char *) nlmsg_data(msg->nm_nlh),
484 msg->nm_nlh->nlmsg_len);
485
486 return nla;
487}
488
489/**
490 * Add a unspecific attribute to netlink message.
491 * @arg msg Netlink message.
492 * @arg attrtype Attribute type.
493 * @arg datalen Length of data to be used as payload.
494 * @arg data Pointer to data to be used as attribute payload.
495 *
496 * Reserves room for a unspecific attribute and copies the provided data
497 * into the message as payload of the attribute. Returns an error if there
498 * is insufficient space for the attribute.
499 *
500 * @see nla_reserve
501 * @return 0 on success or a negative error code.
502 */
503int nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data)
504{
505 struct nlattr *nla;
506
507 nla = nla_reserve(msg, attrtype, datalen);
508 if (!nla) {
509 if (datalen < 0)
510 return -NLE_INVAL;
511
512 return -NLE_NOMEM;
513 }
514
515 if (datalen > 0) {
516 memcpy(nla_data(nla), data, datalen);
517 NL_DBG(2, "msg %p: attr <%p> %d: Wrote %d bytes at offset +%td\n",
518 msg, nla, nla->nla_type, datalen,
519 (char *) nla - (char *) nlmsg_data(msg->nm_nlh));
520 }
521
522 return 0;
523}
524
525/**
526 * Add abstract data as unspecific attribute to netlink message.
527 * @arg msg Netlink message.
528 * @arg attrtype Attribute type.
529 * @arg data Abstract data object.
530 *
531 * Equivalent to nla_put() except that the length of the payload is
532 * derived from the abstract data object.
533 *
534 * @see nla_put
535 * @return 0 on success or a negative error code.
536 */
537int nla_put_data(struct nl_msg *msg, int attrtype, const struct nl_data *data)
538{
539 return nla_put(msg, attrtype, nl_data_get_size(data),
540 nl_data_get(data));
541}
542
543/**
544 * Add abstract address as unspecific attribute to netlink message.
545 * @arg msg Netlink message.
546 * @arg attrtype Attribute type.
547 * @arg addr Abstract address object.
548 *
549 * @see nla_put
550 * @return 0 on success or a negative error code.
551 */
552int nla_put_addr(struct nl_msg *msg, int attrtype, struct nl_addr *addr)
553{
554 if (nl_addr_get_len(addr) == 0)
555 return -NLE_INVAL;
556
557 return nla_put(msg, attrtype, nl_addr_get_len(addr),
559}
560
561/** @} */
562
563/**
564 * @name Integer Attributes
565 */
566
567/**
568 * Add 8 bit signed integer attribute to netlink message.
569 * @arg msg Netlink message.
570 * @arg attrtype Attribute type.
571 * @arg value Numeric value to store as payload.
572 *
573 * @see nla_put
574 * @return 0 on success or a negative error code.
575 */
576int nla_put_s8(struct nl_msg *msg, int attrtype, int8_t value)
577{
578 return nla_put(msg, attrtype, sizeof(int8_t), &value);
579}
580
581/**
582 * Return value of 8 bit signed integer attribute.
583 * @arg nla 8 bit integer attribute
584 *
585 * @return Payload as 8 bit integer.
586 */
587int8_t nla_get_s8(const struct nlattr *nla)
588{
589 return *(const int8_t *) nla_data(nla);
590}
591
592/**
593 * Add 8 bit integer attribute to netlink message.
594 * @arg msg Netlink message.
595 * @arg attrtype Attribute type.
596 * @arg value Numeric value to store as payload.
597 *
598 * @see nla_put
599 * @return 0 on success or a negative error code.
600 */
601int nla_put_u8(struct nl_msg *msg, int attrtype, uint8_t value)
602{
603 return nla_put(msg, attrtype, sizeof(uint8_t), &value);
604}
605
606/**
607 * Return value of 8 bit integer attribute.
608 * @arg nla 8 bit integer attribute
609 *
610 * @return Payload as 8 bit integer.
611 */
612uint8_t nla_get_u8(const struct nlattr *nla)
613{
614 return *(const uint8_t *) nla_data(nla);
615}
616
617/**
618 * Add 16 bit signed integer attribute to netlink message.
619 * @arg msg Netlink message.
620 * @arg attrtype Attribute type.
621 * @arg value Numeric value to store as payload.
622 *
623 * @see nla_put
624 * @return 0 on success or a negative error code.
625 */
626int nla_put_s16(struct nl_msg *msg, int attrtype, int16_t value)
627{
628 return nla_put(msg, attrtype, sizeof(int16_t), &value);
629}
630
631/**
632 * Return payload of 16 bit signed integer attribute.
633 * @arg nla 16 bit integer attribute
634 *
635 * @return Payload as 16 bit integer.
636 */
637int16_t nla_get_s16(const struct nlattr *nla)
638{
639 return *(const int16_t *) nla_data(nla);
640}
641
642/**
643 * Add 16 bit integer attribute to netlink message.
644 * @arg msg Netlink message.
645 * @arg attrtype Attribute type.
646 * @arg value Numeric value to store as payload.
647 *
648 * @see nla_put
649 * @return 0 on success or a negative error code.
650 */
651int nla_put_u16(struct nl_msg *msg, int attrtype, uint16_t value)
652{
653 return nla_put(msg, attrtype, sizeof(uint16_t), &value);
654}
655
656/**
657 * Return payload of 16 bit integer attribute.
658 * @arg nla 16 bit integer attribute
659 *
660 * @return Payload as 16 bit integer.
661 */
662uint16_t nla_get_u16(const struct nlattr *nla)
663{
664 return *(const uint16_t *) nla_data(nla);
665}
666
667/**
668 * Add 32 bit signed integer attribute to netlink message.
669 * @arg msg Netlink message.
670 * @arg attrtype Attribute type.
671 * @arg value Numeric value to store as payload.
672 *
673 * @see nla_put
674 * @return 0 on success or a negative error code.
675 */
676int nla_put_s32(struct nl_msg *msg, int attrtype, int32_t value)
677{
678 return nla_put(msg, attrtype, sizeof(int32_t), &value);
679}
680
681/**
682 * Return payload of 32 bit signed integer attribute.
683 * @arg nla 32 bit integer attribute.
684 *
685 * @return Payload as 32 bit integer.
686 */
687int32_t nla_get_s32(const struct nlattr *nla)
688{
689 return *(const int32_t *) nla_data(nla);
690}
691
692/**
693 * Add 32 bit integer attribute to netlink message.
694 * @arg msg Netlink message.
695 * @arg attrtype Attribute type.
696 * @arg value Numeric value to store as payload.
697 *
698 * @see nla_put
699 * @return 0 on success or a negative error code.
700 */
701int nla_put_u32(struct nl_msg *msg, int attrtype, uint32_t value)
702{
703 return nla_put(msg, attrtype, sizeof(uint32_t), &value);
704}
705
706/**
707 * Return payload of 32 bit integer attribute.
708 * @arg nla 32 bit integer attribute.
709 *
710 * @return Payload as 32 bit integer.
711 */
712uint32_t nla_get_u32(const struct nlattr *nla)
713{
714 return *(const uint32_t *) nla_data(nla);
715}
716
717/**
718 * Add 64 bit signed integer attribute to netlink message.
719 * @arg msg Netlink message.
720 * @arg attrtype Attribute type.
721 * @arg value Numeric value to store as payload.
722 *
723 * @see nla_put
724 * @return 0 on success or a negative error code.
725 */
726int nla_put_s64(struct nl_msg *msg, int attrtype, int64_t value)
727{
728 return nla_put(msg, attrtype, sizeof(int64_t), &value);
729}
730
731/**
732 * Return payload of s64 attribute
733 * @arg nla s64 netlink attribute
734 *
735 * @return Payload as 64 bit integer.
736 */
737int64_t nla_get_s64(const struct nlattr *nla)
738{
739 int64_t tmp = 0;
740
741 if (nla && _nla_len(nla) >= sizeof(tmp))
742 memcpy(&tmp, nla_data(nla), sizeof(tmp));
743
744 return tmp;
745}
746
747/**
748 * Add 64 bit integer attribute to netlink message.
749 * @arg msg Netlink message.
750 * @arg attrtype Attribute type.
751 * @arg value Numeric value to store as payload.
752 *
753 * @see nla_put
754 * @return 0 on success or a negative error code.
755 */
756int nla_put_u64(struct nl_msg *msg, int attrtype, uint64_t value)
757{
758 return nla_put(msg, attrtype, sizeof(uint64_t), &value);
759}
760
761/**
762 * Return payload of u64 attribute
763 * @arg nla u64 netlink attribute
764 *
765 * @return Payload as 64 bit integer.
766 */
767uint64_t nla_get_u64(const struct nlattr *nla)
768{
769 uint64_t tmp = 0;
770
771 if (nla && _nla_len(nla) >= sizeof(tmp))
772 memcpy(&tmp, nla_data(nla), sizeof(tmp));
773
774 return tmp;
775}
776
777/** @} */
778
779/**
780 * @name String Attribute
781 */
782
783/**
784 * Add string attribute to netlink message.
785 * @arg msg Netlink message.
786 * @arg attrtype Attribute type.
787 * @arg str NUL terminated string.
788 *
789 * @see nla_put
790 * @return 0 on success or a negative error code.
791 */
792int nla_put_string(struct nl_msg *msg, int attrtype, const char *str)
793{
794 return nla_put(msg, attrtype, strlen(str) + 1, str);
795}
796
797/**
798 * Return payload of string attribute.
799 * @arg nla String attribute.
800 *
801 * @return Pointer to attribute payload.
802 */
803char *nla_get_string(const struct nlattr *nla)
804{
805 return (char *) nla_data(nla);
806}
807
808char *nla_strdup(const struct nlattr *nla)
809{
810 return strdup(nla_get_string(nla));
811}
812
813/** @} */
814
815/**
816 * @name Flag Attribute
817 */
818
819/**
820 * Add flag netlink attribute to netlink message.
821 * @arg msg Netlink message.
822 * @arg attrtype Attribute type.
823 *
824 * @see nla_put
825 * @return 0 on success or a negative error code.
826 */
827int nla_put_flag(struct nl_msg *msg, int attrtype)
828{
829 return nla_put(msg, attrtype, 0, NULL);
830}
831
832/**
833 * Return true if flag attribute is set.
834 * @arg nla Flag netlink attribute.
835 *
836 * @return True if flag is set, otherwise false.
837 */
838int nla_get_flag(const struct nlattr *nla)
839{
840 return !!nla;
841}
842
843/** @} */
844
845/**
846 * @name Microseconds Attribute
847 */
848
849/**
850 * Add a msecs netlink attribute to a netlink message
851 * @arg n netlink message
852 * @arg attrtype attribute type
853 * @arg msecs number of msecs
854 */
855int nla_put_msecs(struct nl_msg *n, int attrtype, unsigned long msecs)
856{
857 return nla_put_u64(n, attrtype, msecs);
858}
859
860/**
861 * Return payload of msecs attribute
862 * @arg nla msecs netlink attribute
863 *
864 * @return the number of milliseconds.
865 */
866unsigned long nla_get_msecs(const struct nlattr *nla)
867{
868 return nla_get_u64(nla);
869}
870
871/** @} */
872
873/**
874 * @name Nested Attribute
875 */
876
877/**
878 * Add nested attributes to netlink message.
879 * @arg msg Netlink message.
880 * @arg attrtype Attribute type.
881 * @arg nested Message containing attributes to be nested.
882 *
883 * Takes the attributes found in the \a nested message and appends them
884 * to the message \a msg nested in a container of the type \a attrtype.
885 * The \a nested message may not have a family specific header.
886 *
887 * @see nla_put
888 * @return 0 on success or a negative error code.
889 */
890int nla_put_nested(struct nl_msg *msg, int attrtype,
891 const struct nl_msg *nested)
892{
893 NL_DBG(2, "msg %p: attr <> %d: adding msg %p as nested attribute\n",
894 msg, attrtype, nested);
895
896 return nla_put(msg, attrtype, nlmsg_datalen(nested->nm_nlh),
897 nlmsg_data(nested->nm_nlh));
898}
899
900
901/**
902 * Start a new level of nested attributes.
903 * @arg msg Netlink message.
904 * @arg attrtype Attribute type of container.
905 *
906 * @return Pointer to container attribute.
907 */
908struct nlattr *nla_nest_start(struct nl_msg *msg, int attrtype)
909{
910 struct nlattr *start = (struct nlattr *) nlmsg_tail(msg->nm_nlh);
911
912 if (nla_put(msg, NLA_F_NESTED | attrtype, 0, NULL) < 0)
913 return NULL;
914
915 NL_DBG(2, "msg %p: attr <%p> %d: starting nesting\n",
916 msg, start, start->nla_type);
917
918 return start;
919}
920
921static int _nest_end(struct nl_msg *msg, struct nlattr *start, int keep_empty)
922{
923 size_t pad, len;
924
925 len = (char *) nlmsg_tail(msg->nm_nlh) - (char *) start;
926
927 if ( len > USHRT_MAX
928 || (!keep_empty && len == NLA_HDRLEN)) {
929 /*
930 * Max nlattr size exceeded or empty nested attribute, trim the
931 * attribute header again
932 */
933 nla_nest_cancel(msg, start);
934
935 /* Return error only if nlattr size was exceeded */
936 return (len == NLA_HDRLEN) ? 0 : -NLE_ATTRSIZE;
937 }
938
939 start->nla_len = len;
940
941 pad = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) - msg->nm_nlh->nlmsg_len;
942 if (pad > 0) {
943 /*
944 * Data inside attribute does not end at a alignment boundry.
945 * Pad accordingly and accoun for the additional space in
946 * the message. nlmsg_reserve() may never fail in this situation,
947 * the allocate message buffer must be a multiple of NLMSG_ALIGNTO.
948 */
949 if (!nlmsg_reserve(msg, pad, 0))
950 BUG();
951
952 NL_DBG(2, "msg %p: attr <%p> %d: added %zu bytes of padding\n",
953 msg, start, start->nla_type, pad);
954 }
955
956 NL_DBG(2, "msg %p: attr <%p> %d: closing nesting, len=%u\n",
957 msg, start, start->nla_type, start->nla_len);
958
959 return 0;
960}
961
962/**
963 * Finalize nesting of attributes.
964 * @arg msg Netlink message.
965 * @arg start Container attribute as returned from nla_nest_start().
966 *
967 * Corrects the container attribute header to include the appeneded attributes.
968 *
969 * @return 0 on success or a negative error code.
970 */
971int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
972{
973 return _nest_end (msg, start, 0);
974}
975
976/**
977 * Finalize nesting of attributes without stripping off empty attributes.
978 * @arg msg Netlink message.
979 * @arg start Container attribute as returned from nla_nest_start().
980 *
981 * Corrects the container attribute header to include the appeneded attributes.
982 * Keep empty attribute if NO actual attribute payload exists.
983 *
984 * @return 0 on success or a negative error code.
985 */
986int nla_nest_end_keep_empty(struct nl_msg *msg, struct nlattr *start)
987{
988 return _nest_end (msg, start, 1);
989}
990
991/**
992 * Cancel the addition of a nested attribute
993 * @arg msg Netlink message
994 * @arg attr Nested netlink attribute
995 *
996 * Removes any partially added nested Netlink attribute from the message
997 * by resetting the message to the size before the call to nla_nest_start()
998 * and by overwriting any potentially touched message segments with 0.
999 */
1000void nla_nest_cancel(struct nl_msg *msg, const struct nlattr *attr)
1001{
1002 ssize_t len;
1003
1004 if (!attr) {
1005 /* For robustness, allow a NULL attr to do nothing. NULL is also
1006 * what nla_nest_start() when out of buffer space.
1007 *
1008 * Warning, before libnl-3.8, the function did not accept NULL!
1009 * If you care, catch NULL yourself. */
1010 return;
1011 }
1012
1013 len = (char *) nlmsg_tail(msg->nm_nlh) - (char *) attr;
1014 if (len < 0)
1015 BUG();
1016 else if (len > 0) {
1017 msg->nm_nlh->nlmsg_len -= len;
1018 memset(nlmsg_tail(msg->nm_nlh), 0, len);
1019 }
1020}
1021
1022/**
1023 * Create attribute index based on nested attribute
1024 * @arg tb Index array to be filled (maxtype+1 elements).
1025 * @arg maxtype Maximum attribute type expected and accepted.
1026 * @arg nla Nested Attribute.
1027 * @arg policy Attribute validation policy.
1028 *
1029 * Feeds the stream of attributes nested into the specified attribute
1030 * to nla_parse().
1031 *
1032 * @see nla_parse
1033 * @return 0 on success or a negative error code.
1034 */
1035int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla,
1036 const struct nla_policy *policy)
1037{
1038 return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
1039}
1040
1041/**
1042 * Return true if attribute has NLA_F_NESTED flag set
1043 * @arg attr Netlink attribute
1044 *
1045 * @return True if attribute has NLA_F_NESTED flag set, oterhwise False.
1046 */
1047int nla_is_nested(const struct nlattr *attr)
1048{
1049 return !!(attr->nla_type & NLA_F_NESTED);
1050}
1051
1052/** @} */
1053
1054/** @} */
void * nl_addr_get_binary_addr(const struct nl_addr *addr)
Get binary address of abstract address object.
Definition addr.c:943
unsigned int nl_addr_get_len(const struct nl_addr *addr)
Get length of binary address of abstract address object.
Definition addr.c:955
int nla_validate(const struct nlattr *head, int len, int maxtype, const struct nla_policy *policy)
Validate a stream of attributes.
Definition attr.c:294
int nla_put_s16(struct nl_msg *msg, int attrtype, int16_t value)
Add 16 bit signed integer attribute to netlink message.
Definition attr.c:626
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition attr.c:712
int nla_put_u16(struct nl_msg *msg, int attrtype, uint16_t value)
Add 16 bit integer attribute to netlink message.
Definition attr.c:651
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition attr.c:662
int nla_strcmp(const struct nlattr *nla, const char *str)
Compare string attribute payload with string.
Definition attr.c:426
int nla_put_data(struct nl_msg *msg, int attrtype, const struct nl_data *data)
Add abstract data as unspecific attribute to netlink message.
Definition attr.c:537
int nla_put_nested(struct nl_msg *msg, int attrtype, const struct nl_msg *nested)
Add nested attributes to netlink message.
Definition attr.c:890
struct nlattr * nla_next(const struct nlattr *nla, int *remaining)
Return next attribute in a stream of attributes.
Definition attr.c:172
int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, const struct nla_policy *policy)
Create attribute index based on a stream of attributes.
Definition attr.c:243
int nla_put_string(struct nl_msg *msg, int attrtype, const char *str)
Add string attribute to netlink message.
Definition attr.c:792
uint64_t nla_get_u64(const struct nlattr *nla)
Return payload of u64 attribute.
Definition attr.c:767
int nla_get_flag(const struct nlattr *nla)
Return true if flag attribute is set.
Definition attr.c:838
int nla_type(const struct nlattr *nla)
Return type of the attribute.
Definition attr.c:108
int nla_put_u64(struct nl_msg *msg, int attrtype, uint64_t value)
Add 64 bit integer attribute to netlink message.
Definition attr.c:756
int nla_ok(const struct nlattr *nla, int remaining)
Check if the attribute header and payload can be accessed safely.
Definition attr.c:147
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
Definition attr.c:119
int nla_is_nested(const struct nlattr *attr)
Return true if attribute has NLA_F_NESTED flag set.
Definition attr.c:1047
int nla_put_u32(struct nl_msg *msg, int attrtype, uint32_t value)
Add 32 bit integer attribute to netlink message.
Definition attr.c:701
int nla_put_addr(struct nl_msg *msg, int attrtype, struct nl_addr *addr)
Add abstract address as unspecific attribute to netlink message.
Definition attr.c:552
int nla_memcmp(const struct nlattr *nla, const void *data, size_t size)
Compare attribute payload with memory area.
Definition attr.c:408
int nla_put_s64(struct nl_msg *msg, int attrtype, int64_t value)
Add 64 bit signed integer attribute to netlink message.
Definition attr.c:726
#define nla_for_each_attr(pos, head, len, rem)
Iterate over a stream of attributes.
Definition attr.h:312
int nla_put_msecs(struct nl_msg *n, int attrtype, unsigned long msecs)
Add a msecs netlink attribute to a netlink message.
Definition attr.c:855
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
Definition attr.c:612
int nla_attr_size(int payload)
Return size of attribute whithout padding.
Definition attr.c:54
int16_t nla_get_s16(const struct nlattr *nla)
Return payload of 16 bit signed integer attribute.
Definition attr.c:637
int64_t nla_get_s64(const struct nlattr *nla)
Return payload of s64 attribute.
Definition attr.c:737
int nla_put_flag(struct nl_msg *msg, int attrtype)
Add flag netlink attribute to netlink message.
Definition attr.c:827
int nla_put_s32(struct nl_msg *msg, int attrtype, int32_t value)
Add 32 bit signed integer attribute to netlink message.
Definition attr.c:676
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
Definition attr.c:353
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition attr.c:908
unsigned long nla_get_msecs(const struct nlattr *nla)
Return payload of msecs attribute.
Definition attr.c:866
size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
Copy string attribute payload to a buffer.
Definition attr.c:381
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
Definition attr.c:1035
char * nla_get_string(const struct nlattr *nla)
Return payload of string attribute.
Definition attr.c:803
int32_t nla_get_s32(const struct nlattr *nla)
Return payload of 32 bit signed integer attribute.
Definition attr.c:687
void nla_nest_cancel(struct nl_msg *msg, const struct nlattr *attr)
Cancel the addition of a nested attribute.
Definition attr.c:1000
int nla_len(const struct nlattr *nla)
Return length of the payload .
Definition attr.c:130
int nla_put_u8(struct nl_msg *msg, int attrtype, uint8_t value)
Add 8 bit integer attribute to netlink message.
Definition attr.c:601
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition attr.c:971
int nla_nest_end_keep_empty(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes without stripping off empty attributes.
Definition attr.c:986
int8_t nla_get_s8(const struct nlattr *nla)
Return value of 8 bit signed integer attribute.
Definition attr.c:587
struct nlattr * nla_find(const struct nlattr *head, int len, int attrtype)
Find a single attribute in a stream of attributes.
Definition attr.c:323
int nla_padlen(int payload)
Return length of padding at the tail of the attribute.
Definition attr.c:90
int nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data)
Add a unspecific attribute to netlink message.
Definition attr.c:503
int nla_put_s8(struct nl_msg *msg, int attrtype, int8_t value)
Add 8 bit signed integer attribute to netlink message.
Definition attr.c:576
struct nlattr * nla_reserve(struct nl_msg *msg, int attrtype, int attrlen)
Reserve space for a attribute.
Definition attr.c:459
int nla_total_size(int payload)
Return size of attribute including padding.
Definition attr.c:72
@ NLA_U64
64 bit integer
Definition attr.h:38
@ NLA_STRING
NUL terminated character string.
Definition attr.h:39
@ NLA_UNSPEC
Unspecified type, binary data chunk.
Definition attr.h:34
@ NLA_U8
8 bit integer
Definition attr.h:35
@ NLA_FLAG
Flag.
Definition attr.h:40
@ NLA_U16
16 bit integer
Definition attr.h:36
@ NLA_U32
32 bit integer
Definition attr.h:37
size_t nl_data_get_size(const struct nl_data *data)
Get size of data buffer of abstract data object.
Definition data.c:166
void * nl_data_get(const struct nl_data *data)
Get data buffer of abstract data object.
Definition data.c:154
void * nlmsg_data(const struct nlmsghdr *nlh)
Return pointer to message payload.
Definition msg.c:108
void * nlmsg_reserve(struct nl_msg *n, size_t len, int pad)
Reserve room for additional data in a netlink message.
Definition msg.c:418
int nlmsg_datalen(const struct nlmsghdr *nlh)
Return length of message payload.
Definition msg.c:124
Attribute validation policy.
Definition attr.h:63
uint16_t minlen
Minimal length of payload required.
Definition attr.h:68
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition attr.h:65