xref: /aosp_15_r20/external/libnl/lib/attr.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3  * Copyright (c) 2003-2013 Thomas Graf <[email protected]>
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  */
nla_attr_size(int payload)54 int 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  */
nla_total_size(int payload)72 int 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  */
nla_padlen(int payload)90 int 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  */
nla_type(const struct nlattr * nla)108 int 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  */
nla_data(const struct nlattr * nla)119 void *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  */
nla_len(const struct nlattr * nla)130 int 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  */
nla_ok(const struct nlattr * nla,int remaining)147 int 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  */
nla_next(const struct nlattr * nla,int * remaining)172 struct 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 
180 static 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 
validate_nla(const struct nlattr * nla,int maxtype,const struct nla_policy * policy)189 static 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 
196 	if (type < 0 || type > maxtype)
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  */
nla_parse(struct nlattr * tb[],int maxtype,struct nlattr * head,int len,const struct nla_policy * policy)243 int 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  */
nla_validate(const struct nlattr * head,int len,int maxtype,const struct nla_policy * policy)294 int 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;
307 errout:
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  */
nla_find(const struct nlattr * head,int len,int attrtype)323 struct 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  */
nla_memcpy(void * dest,const struct nlattr * src,int count)353 int 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  */
nla_strlcpy(char * dst,const struct nlattr * nla,size_t dstsize)381 size_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  */
nla_memcmp(const struct nlattr * nla,const void * data,size_t size)408 int 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  */
nla_strcmp(const struct nlattr * nla,const char * str)426 int 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  */
nla_reserve(struct nl_msg * msg,int attrtype,int attrlen)459 struct 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  */
nla_put(struct nl_msg * msg,int attrtype,int datalen,const void * data)503 int 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  */
nla_put_data(struct nl_msg * msg,int attrtype,const struct nl_data * data)537 int 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  */
nla_put_addr(struct nl_msg * msg,int attrtype,struct nl_addr * addr)552 int 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),
558 		       nl_addr_get_binary_addr(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  */
nla_put_s8(struct nl_msg * msg,int attrtype,int8_t value)576 int 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  */
nla_get_s8(const struct nlattr * nla)587 int8_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  */
nla_put_u8(struct nl_msg * msg,int attrtype,uint8_t value)601 int 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  */
nla_get_u8(const struct nlattr * nla)612 uint8_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  */
nla_put_s16(struct nl_msg * msg,int attrtype,int16_t value)626 int 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  */
nla_get_s16(const struct nlattr * nla)637 int16_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  */
nla_put_u16(struct nl_msg * msg,int attrtype,uint16_t value)651 int 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  */
nla_get_u16(const struct nlattr * nla)662 uint16_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  */
nla_put_s32(struct nl_msg * msg,int attrtype,int32_t value)676 int 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  */
nla_get_s32(const struct nlattr * nla)687 int32_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  */
nla_put_u32(struct nl_msg * msg,int attrtype,uint32_t value)701 int 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  */
nla_get_u32(const struct nlattr * nla)712 uint32_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  */
nla_put_s64(struct nl_msg * msg,int attrtype,int64_t value)726 int 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  */
nla_get_s64(const struct nlattr * nla)737 int64_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  */
nla_put_u64(struct nl_msg * msg,int attrtype,uint64_t value)756 int 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  */
nla_get_u64(const struct nlattr * nla)767 uint64_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  */
nla_put_string(struct nl_msg * msg,int attrtype,const char * str)792 int 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  */
nla_get_string(const struct nlattr * nla)803 char *nla_get_string(const struct nlattr *nla)
804 {
805 	return (char *) nla_data(nla);
806 }
807 
nla_strdup(const struct nlattr * nla)808 char *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  */
nla_put_flag(struct nl_msg * msg,int attrtype)827 int 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  */
nla_get_flag(const struct nlattr * nla)838 int 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  */
nla_put_msecs(struct nl_msg * n,int attrtype,unsigned long msecs)855 int 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  */
nla_get_msecs(const struct nlattr * nla)866 unsigned 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  */
nla_put_nested(struct nl_msg * msg,int attrtype,const struct nl_msg * nested)890 int 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  */
nla_nest_start(struct nl_msg * msg,int attrtype)908 struct 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 
_nest_end(struct nl_msg * msg,struct nlattr * start,int keep_empty)921 static 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  */
nla_nest_end(struct nl_msg * msg,struct nlattr * start)971 int 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  */
nla_nest_end_keep_empty(struct nl_msg * msg,struct nlattr * start)986 int 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  */
nla_nest_cancel(struct nl_msg * msg,const struct nlattr * attr)1000 void 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  */
nla_parse_nested(struct nlattr * tb[],int maxtype,struct nlattr * nla,const struct nla_policy * policy)1035 int 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  */
nla_is_nested(const struct nlattr * attr)1047 int nla_is_nested(const struct nlattr *attr)
1048 {
1049 	return !!(attr->nla_type & NLA_F_NESTED);
1050 }
1051 
1052 /** @} */
1053 
1054 /** @} */
1055