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