• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * lib/attr.c		Netlink Attributes
3  *
4  *	This library is free software; you can redistribute it and/or
5  *	modify it under the terms of the GNU Lesser General Public
6  *	License as published by the Free Software Foundation version 2.1
7  *	of the License.
8  *
9  * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
10  */
11 
12 #include <netlink-private/netlink.h>
13 #include <netlink/netlink.h>
14 #include <netlink/utils.h>
15 #include <netlink/addr.h>
16 #include <netlink/attr.h>
17 #include <netlink/msg.h>
18 #include <linux/socket.h>
19 
20 /**
21  * @ingroup msg
22  * @defgroup attr Attributes
23  * Netlink Attributes Construction/Parsing Interface
24  *
25  * Related sections in the development guide:
26  * - @core_doc{core_attr,Netlink Attributes}
27  *
28  * @{
29  *
30  * Header
31  * ------
32  * ~~~~{.c}
33  * #include <netlink/attr.h>
34  * ~~~~
35  */
36 
37 /**
38  * @name Attribute Size Calculation
39  * @{
40  */
41 
42 /**
43  * Return size of attribute whithout padding.
44  * @arg payload		Payload length of attribute.
45  *
46  * @code
47  *    <-------- nla_attr_size(payload) --------->
48  *   +------------------+- - -+- - - - - - - - - +- - -+
49  *   | Attribute Header | Pad |     Payload      | Pad |
50  *   +------------------+- - -+- - - - - - - - - +- - -+
51  * @endcode
52  *
53  * @return Size of attribute in bytes without padding.
54  */
nla_attr_size(int payload)55 int nla_attr_size(int payload)
56 {
57 	return NLA_HDRLEN + payload;
58 }
59 
60 /**
61  * Return size of attribute including padding.
62  * @arg payload		Payload length of attribute.
63  *
64  * @code
65  *    <----------- nla_total_size(payload) ----------->
66  *   +------------------+- - -+- - - - - - - - - +- - -+
67  *   | Attribute Header | Pad |     Payload      | Pad |
68  *   +------------------+- - -+- - - - - - - - - +- - -+
69  * @endcode
70  *
71  * @return Size of attribute in bytes.
72  */
nla_total_size(int payload)73 int nla_total_size(int payload)
74 {
75 	return NLA_ALIGN(nla_attr_size(payload));
76 }
77 
78 /**
79  * Return length of padding at the tail of the attribute.
80  * @arg payload		Payload length of attribute.
81  *
82  * @code
83  *   +------------------+- - -+- - - - - - - - - +- - -+
84  *   | Attribute Header | Pad |     Payload      | Pad |
85  *   +------------------+- - -+- - - - - - - - - +- - -+
86  *                                                <--->
87  * @endcode
88  *
89  * @return Length of padding in bytes.
90  */
nla_padlen(int payload)91 int nla_padlen(int payload)
92 {
93 	return nla_total_size(payload) - nla_attr_size(payload);
94 }
95 
96 /** @} */
97 
98 /**
99  * @name Parsing Attributes
100  * @{
101  */
102 
103 /**
104  * Return type of the attribute.
105  * @arg nla		Attribute.
106  *
107  * @return Type of attribute.
108  */
nla_type(const struct nlattr * nla)109 int nla_type(const struct nlattr *nla)
110 {
111 	return nla->nla_type & NLA_TYPE_MASK;
112 }
113 
114 /**
115  * Return pointer to the payload section.
116  * @arg nla		Attribute.
117  *
118  * @return Pointer to start of payload section.
119  */
nla_data(const struct nlattr * nla)120 void *nla_data(const struct nlattr *nla)
121 {
122 	return (char *) nla + NLA_HDRLEN;
123 }
124 
125 /**
126  * Return length of the payload .
127  * @arg nla		Attribute
128  *
129  * @return Length of payload in bytes.
130  */
nla_len(const struct nlattr * nla)131 int nla_len(const struct nlattr *nla)
132 {
133 	return nla->nla_len - NLA_HDRLEN;
134 }
135 
136 /**
137  * Check if the attribute header and payload can be accessed safely.
138  * @arg nla		Attribute of any kind.
139  * @arg remaining	Number of bytes remaining in attribute stream.
140  *
141  * Verifies that the header and payload do not exceed the number of
142  * bytes left in the attribute stream. This function must be called
143  * before access the attribute header or payload when iterating over
144  * the attribute stream using nla_next().
145  *
146  * @return True if the attribute can be accessed safely, false otherwise.
147  */
nla_ok(const struct nlattr * nla,int remaining)148 int nla_ok(const struct nlattr *nla, int remaining)
149 {
150 	return remaining >= sizeof(*nla) &&
151 	       nla->nla_len >= sizeof(*nla) &&
152 	       nla->nla_len <= remaining;
153 }
154 
155 /**
156  * Return next attribute in a stream of attributes.
157  * @arg nla		Attribute of any kind.
158  * @arg remaining	Variable to count remaining bytes in stream.
159  *
160  * Calculates the offset to the next attribute based on the attribute
161  * given. The attribute provided is assumed to be accessible, the
162  * caller is responsible to use nla_ok() beforehand. The offset (length
163  * of specified attribute including padding) is then subtracted from
164  * the remaining bytes variable and a pointer to the next attribute is
165  * returned.
166  *
167  * nla_next() can be called as long as remainig is >0.
168  *
169  * @return Pointer to next attribute.
170  */
nla_next(const struct nlattr * nla,int * remaining)171 struct nlattr *nla_next(const struct nlattr *nla, int *remaining)
172 {
173 	int totlen = NLA_ALIGN(nla->nla_len);
174 
175 	*remaining -= totlen;
176 	return (struct nlattr *) ((char *) nla + totlen);
177 }
178 
179 static uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = {
180 	[NLA_U8]	= sizeof(uint8_t),
181 	[NLA_U16]	= sizeof(uint16_t),
182 	[NLA_U32]	= sizeof(uint32_t),
183 	[NLA_U64]	= sizeof(uint64_t),
184 	[NLA_STRING]	= 1,
185 	[NLA_FLAG]	= 0,
186 };
187 
validate_nla(struct nlattr * nla,int maxtype,struct nla_policy * policy)188 static int validate_nla(struct nlattr *nla, int maxtype,
189 			struct nla_policy *policy)
190 {
191 	struct nla_policy *pt;
192 	unsigned int minlen = 0;
193 	int type = nla_type(nla);
194 
195 	if (type < 0 || type > maxtype)
196 		return 0;
197 
198 	pt = &policy[type];
199 
200 	if (pt->type > NLA_TYPE_MAX)
201 		BUG();
202 
203 	if (pt->minlen)
204 		minlen = pt->minlen;
205 	else if (pt->type != NLA_UNSPEC)
206 		minlen = nla_attr_minlen[pt->type];
207 
208 	if (nla_len(nla) < minlen)
209 		return -NLE_RANGE;
210 
211 	if (pt->maxlen && nla_len(nla) > pt->maxlen)
212 		return -NLE_RANGE;
213 
214 	if (pt->type == NLA_STRING) {
215 		char *data = nla_data(nla);
216 		if (data[nla_len(nla) - 1] != '\0')
217 			return -NLE_INVAL;
218 	}
219 
220 	return 0;
221 }
222 
223 
224 /**
225  * Create attribute index based on a stream of attributes.
226  * @arg tb		Index array to be filled (maxtype+1 elements).
227  * @arg maxtype		Maximum attribute type expected and accepted.
228  * @arg head		Head of attribute stream.
229  * @arg len		Length of attribute stream.
230  * @arg policy		Attribute validation policy.
231  *
232  * Iterates over the stream of attributes and stores a pointer to each
233  * attribute in the index array using the attribute type as index to
234  * the array. Attribute with a type greater than the maximum type
235  * specified will be silently ignored in order to maintain backwards
236  * compatibility. If \a policy is not NULL, the attribute will be
237  * validated using the specified policy.
238  *
239  * @see nla_validate
240  * @return 0 on success or a negative error code.
241  */
nla_parse(struct nlattr * tb[],int maxtype,struct nlattr * head,int len,struct nla_policy * policy)242 int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
243 	      struct nla_policy *policy)
244 {
245 	struct nlattr *nla;
246 	int rem, err;
247 
248 	memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
249 
250 	nla_for_each_attr(nla, head, len, rem) {
251 		int type = nla_type(nla);
252 
253 		if (type > maxtype)
254 			continue;
255 
256 		if (policy) {
257 			err = validate_nla(nla, maxtype, policy);
258 			if (err < 0)
259 				goto errout;
260 		}
261 
262 		if (tb[type])
263 			NL_DBG(1, "Attribute of type %#x found multiple times in message, "
264 				  "previous attribute is being ignored.\n", type);
265 
266 		tb[type] = nla;
267 	}
268 
269 	if (rem > 0)
270 		NL_DBG(1, "netlink: %d bytes leftover after parsing "
271 		       "attributes.\n", rem);
272 
273 	err = 0;
274 errout:
275 	return err;
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(struct nlattr * head,int len,int maxtype,struct nla_policy * policy)294 int nla_validate(struct nlattr *head, int len, int maxtype,
295 		 struct nla_policy *policy)
296 {
297 	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(struct nlattr * head,int len,int attrtype)323 struct nlattr *nla_find(struct nlattr *head, int len, int attrtype)
324 {
325 	struct nlattr *nla;
326 	int rem;
327 
328 	nla_for_each_attr(nla, head, len, rem)
329 		if (nla_type(nla) == attrtype)
330 			return 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,struct nlattr * src,int count)353 int nla_memcpy(void *dest, struct nlattr *src, int count)
354 {
355 	int minlen;
356 
357 	if (!src)
358 		return 0;
359 
360 	minlen = min_t(int, count, nla_len(src));
361 	memcpy(dest, nla_data(src), minlen);
362 
363 	return minlen;
364 }
365 
366 /**
367  * Copy string attribute payload to a buffer.
368  * @arg dst		Pointer to destination buffer.
369  * @arg nla		Attribute of type NLA_STRING.
370  * @arg dstsize		Size of destination buffer in bytes.
371  *
372  * Copies at most dstsize - 1 bytes to the destination buffer.
373  * The result is always a valid NUL terminated string. Unlike
374  * strlcpy the destination buffer is always padded out.
375  *
376  * @return The length of string attribute without the terminating NUL.
377  */
nla_strlcpy(char * dst,const struct nlattr * nla,size_t dstsize)378 size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
379 {
380 	size_t srclen = nla_len(nla);
381 	char *src = nla_data(nla);
382 
383 	if (srclen > 0 && src[srclen - 1] == '\0')
384 		srclen--;
385 
386 	if (dstsize > 0) {
387 		size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
388 
389 		memset(dst, 0, dstsize);
390 		memcpy(dst, src, len);
391 	}
392 
393 	return srclen;
394 }
395 
396 /**
397  * Compare attribute payload with memory area.
398  * @arg nla		Attribute.
399  * @arg data		Memory area to compare to.
400  * @arg size		Number of bytes to compare.
401  *
402  * @see memcmp(3)
403  * @return An integer less than, equal to, or greater than zero.
404  */
nla_memcmp(const struct nlattr * nla,const void * data,size_t size)405 int nla_memcmp(const struct nlattr *nla, const void *data, size_t size)
406 {
407 	int d = nla_len(nla) - size;
408 
409 	if (d == 0)
410 		d = memcmp(nla_data(nla), data, size);
411 
412 	return d;
413 }
414 
415 /**
416  * Compare string attribute payload with string
417  * @arg nla		Attribute of type NLA_STRING.
418  * @arg str		NUL terminated string.
419  *
420  * @see strcmp(3)
421  * @return An integer less than, equal to, or greater than zero.
422  */
nla_strcmp(const struct nlattr * nla,const char * str)423 int nla_strcmp(const struct nlattr *nla, const char *str)
424 {
425 	int len = strlen(str) + 1;
426 	int d = nla_len(nla) - len;
427 
428 	if (d == 0)
429 		d = memcmp(nla_data(nla), str, len);
430 
431 	return d;
432 }
433 
434 /** @} */
435 
436 /**
437  * @name Unspecific Attribute
438  * @{
439  */
440 
441 /**
442  * Reserve space for a attribute.
443  * @arg msg		Netlink Message.
444  * @arg attrtype	Attribute Type.
445  * @arg attrlen		Length of payload.
446  *
447  * Reserves room for a attribute in the specified netlink message and
448  * fills in the attribute header (type, length). Returns NULL if there
449  * is unsuficient space for the attribute.
450  *
451  * Any padding between payload and the start of the next attribute is
452  * zeroed out.
453  *
454  * @return Pointer to start of attribute or NULL on failure.
455  */
nla_reserve(struct nl_msg * msg,int attrtype,int attrlen)456 struct nlattr *nla_reserve(struct nl_msg *msg, int attrtype, int attrlen)
457 {
458 	struct nlattr *nla;
459 	int tlen;
460 
461 	if (attrlen < 0)
462 		return NULL;
463 
464 	tlen = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) + nla_total_size(attrlen);
465 
466 	if (tlen > msg->nm_size)
467 		return NULL;
468 
469 	nla = (struct nlattr *) nlmsg_tail(msg->nm_nlh);
470 	nla->nla_type = attrtype;
471 	nla->nla_len = nla_attr_size(attrlen);
472 
473 	if (attrlen)
474 		memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen));
475 	msg->nm_nlh->nlmsg_len = tlen;
476 
477 	NL_DBG(2, "msg %p: attr <%p> %d: Reserved %d (%d) bytes at offset +%td "
478 		  "nlmsg_len=%d\n", msg, nla, nla->nla_type,
479 		  nla_total_size(attrlen), attrlen,
480 		  (void *) nla - nlmsg_data(msg->nm_nlh),
481 		  msg->nm_nlh->nlmsg_len);
482 
483 	return nla;
484 }
485 
486 /**
487  * Add a unspecific attribute to netlink message.
488  * @arg msg		Netlink message.
489  * @arg attrtype	Attribute type.
490  * @arg datalen		Length of data to be used as payload.
491  * @arg data		Pointer to data to be used as attribute payload.
492  *
493  * Reserves room for a unspecific attribute and copies the provided data
494  * into the message as payload of the attribute. Returns an error if there
495  * is insufficient space for the attribute.
496  *
497  * @see nla_reserve
498  * @return 0 on success or a negative error code.
499  */
nla_put(struct nl_msg * msg,int attrtype,int datalen,const void * data)500 int nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data)
501 {
502 	struct nlattr *nla;
503 
504 	if (datalen < 0)
505 		return -NLE_RANGE;
506 
507 	nla = nla_reserve(msg, attrtype, datalen);
508 	if (!nla)
509 		return -NLE_NOMEM;
510 
511 	if (datalen > 0) {
512 		memcpy(nla_data(nla), data, datalen);
513 		NL_DBG(2, "msg %p: attr <%p> %d: Wrote %d bytes at offset +%td\n",
514 		       msg, nla, nla->nla_type, datalen,
515 		       (void *) nla - nlmsg_data(msg->nm_nlh));
516 	}
517 
518 	return 0;
519 }
520 
521 /**
522  * Add abstract data as unspecific attribute to netlink message.
523  * @arg msg		Netlink message.
524  * @arg attrtype	Attribute type.
525  * @arg data		Abstract data object.
526  *
527  * Equivalent to nla_put() except that the length of the payload is
528  * derived from the abstract data object.
529  *
530  * @see nla_put
531  * @return 0 on success or a negative error code.
532  */
nla_put_data(struct nl_msg * msg,int attrtype,struct nl_data * data)533 int nla_put_data(struct nl_msg *msg, int attrtype, struct nl_data *data)
534 {
535 	return nla_put(msg, attrtype, nl_data_get_size(data),
536 		       nl_data_get(data));
537 }
538 
539 /**
540  * Add abstract address as unspecific attribute to netlink message.
541  * @arg msg		Netlink message.
542  * @arg attrtype	Attribute type.
543  * @arg addr		Abstract address object.
544  *
545  * @see nla_put
546  * @return 0 on success or a negative error code.
547  */
nla_put_addr(struct nl_msg * msg,int attrtype,struct nl_addr * addr)548 int nla_put_addr(struct nl_msg *msg, int attrtype, struct nl_addr *addr)
549 {
550 	return nla_put(msg, attrtype, nl_addr_get_len(addr),
551 		       nl_addr_get_binary_addr(addr));
552 }
553 
554 /** @} */
555 
556 /**
557  * @name Integer Attributes
558  */
559 
560 /**
561  * Add 8 bit integer attribute to netlink message.
562  * @arg msg		Netlink message.
563  * @arg attrtype	Attribute type.
564  * @arg value		Numeric value to store as payload.
565  *
566  * @see nla_put
567  * @return 0 on success or a negative error code.
568  */
nla_put_u8(struct nl_msg * msg,int attrtype,uint8_t value)569 int nla_put_u8(struct nl_msg *msg, int attrtype, uint8_t value)
570 {
571 	return nla_put(msg, attrtype, sizeof(uint8_t), &value);
572 }
573 
574 /**
575  * Return value of 8 bit integer attribute.
576  * @arg nla		8 bit integer attribute
577  *
578  * @return Payload as 8 bit integer.
579  */
nla_get_u8(struct nlattr * nla)580 uint8_t nla_get_u8(struct nlattr *nla)
581 {
582 	return *(uint8_t *) nla_data(nla);
583 }
584 
585 /**
586  * Add 16 bit integer attribute to netlink message.
587  * @arg msg		Netlink message.
588  * @arg attrtype	Attribute type.
589  * @arg value		Numeric value to store as payload.
590  *
591  * @see nla_put
592  * @return 0 on success or a negative error code.
593  */
nla_put_u16(struct nl_msg * msg,int attrtype,uint16_t value)594 int nla_put_u16(struct nl_msg *msg, int attrtype, uint16_t value)
595 {
596 	return nla_put(msg, attrtype, sizeof(uint16_t), &value);
597 }
598 
599 /**
600  * Return payload of 16 bit integer attribute.
601  * @arg nla		16 bit integer attribute
602  *
603  * @return Payload as 16 bit integer.
604  */
nla_get_u16(struct nlattr * nla)605 uint16_t nla_get_u16(struct nlattr *nla)
606 {
607 	return *(uint16_t *) nla_data(nla);
608 }
609 
610 /**
611  * Add 32 bit integer attribute to netlink message.
612  * @arg msg		Netlink message.
613  * @arg attrtype	Attribute type.
614  * @arg value		Numeric value to store as payload.
615  *
616  * @see nla_put
617  * @return 0 on success or a negative error code.
618  */
nla_put_u32(struct nl_msg * msg,int attrtype,uint32_t value)619 int nla_put_u32(struct nl_msg *msg, int attrtype, uint32_t value)
620 {
621 	return nla_put(msg, attrtype, sizeof(uint32_t), &value);
622 }
623 
624 /**
625  * Return payload of 32 bit integer attribute.
626  * @arg nla		32 bit integer attribute.
627  *
628  * @return Payload as 32 bit integer.
629  */
nla_get_u32(struct nlattr * nla)630 uint32_t nla_get_u32(struct nlattr *nla)
631 {
632 	return *(uint32_t *) nla_data(nla);
633 }
634 
635 /**
636  * Add 64 bit integer attribute to netlink message.
637  * @arg msg		Netlink message.
638  * @arg attrtype	Attribute type.
639  * @arg value		Numeric value to store as payload.
640  *
641  * @see nla_put
642  * @return 0 on success or a negative error code.
643  */
nla_put_u64(struct nl_msg * msg,int attrtype,uint64_t value)644 int nla_put_u64(struct nl_msg *msg, int attrtype, uint64_t value)
645 {
646 	return nla_put(msg, attrtype, sizeof(uint64_t), &value);
647 }
648 
649 /**
650  * Return payload of u64 attribute
651  * @arg nla		u64 netlink attribute
652  *
653  * @return Payload as 64 bit integer.
654  */
nla_get_u64(struct nlattr * nla)655 uint64_t nla_get_u64(struct nlattr *nla)
656 {
657 	uint64_t tmp = 0;
658 
659 	if (nla && nla_len(nla) >= sizeof(tmp))
660 		memcpy(&tmp, nla_data(nla), sizeof(tmp));
661 
662 	return tmp;
663 }
664 
665 /** @} */
666 
667 /**
668  * @name String Attribute
669  */
670 
671 /**
672  * Add string attribute to netlink message.
673  * @arg msg		Netlink message.
674  * @arg attrtype	Attribute type.
675  * @arg str		NUL terminated string.
676  *
677  * @see nla_put
678  * @return 0 on success or a negative error code.
679  */
nla_put_string(struct nl_msg * msg,int attrtype,const char * str)680 int nla_put_string(struct nl_msg *msg, int attrtype, const char *str)
681 {
682 	return nla_put(msg, attrtype, strlen(str) + 1, str);
683 }
684 
685 /**
686  * Return payload of string attribute.
687  * @arg nla		String attribute.
688  *
689  * @return Pointer to attribute payload.
690  */
nla_get_string(struct nlattr * nla)691 char *nla_get_string(struct nlattr *nla)
692 {
693 	return (char *) nla_data(nla);
694 }
695 
nla_strdup(struct nlattr * nla)696 char *nla_strdup(struct nlattr *nla)
697 {
698 	return strdup(nla_get_string(nla));
699 }
700 
701 /** @} */
702 
703 /**
704  * @name Flag Attribute
705  */
706 
707 /**
708  * Add flag netlink attribute to netlink message.
709  * @arg msg		Netlink message.
710  * @arg attrtype	Attribute type.
711  *
712  * @see nla_put
713  * @return 0 on success or a negative error code.
714  */
nla_put_flag(struct nl_msg * msg,int attrtype)715 int nla_put_flag(struct nl_msg *msg, int attrtype)
716 {
717 	return nla_put(msg, attrtype, 0, NULL);
718 }
719 
720 /**
721  * Return true if flag attribute is set.
722  * @arg nla		Flag netlink attribute.
723  *
724  * @return True if flag is set, otherwise false.
725  */
nla_get_flag(struct nlattr * nla)726 int nla_get_flag(struct nlattr *nla)
727 {
728 	return !!nla;
729 }
730 
731 /** @} */
732 
733 /**
734  * @name Microseconds Attribute
735  */
736 
737 /**
738  * Add a msecs netlink attribute to a netlink message
739  * @arg n		netlink message
740  * @arg attrtype	attribute type
741  * @arg msecs 		number of msecs
742  */
nla_put_msecs(struct nl_msg * n,int attrtype,unsigned long msecs)743 int nla_put_msecs(struct nl_msg *n, int attrtype, unsigned long msecs)
744 {
745 	return nla_put_u64(n, attrtype, msecs);
746 }
747 
748 /**
749  * Return payload of msecs attribute
750  * @arg nla		msecs netlink attribute
751  *
752  * @return the number of milliseconds.
753  */
nla_get_msecs(struct nlattr * nla)754 unsigned long nla_get_msecs(struct nlattr *nla)
755 {
756 	return nla_get_u64(nla);
757 }
758 
759 /** @} */
760 
761 /**
762  * @name Nested Attribute
763  */
764 
765 /**
766  * Add nested attributes to netlink message.
767  * @arg msg		Netlink message.
768  * @arg attrtype	Attribute type.
769  * @arg nested		Message containing attributes to be nested.
770  *
771  * Takes the attributes found in the \a nested message and appends them
772  * to the message \a msg nested in a container of the type \a attrtype.
773  * The \a nested message may not have a family specific header.
774  *
775  * @see nla_put
776  * @return 0 on success or a negative error code.
777  */
nla_put_nested(struct nl_msg * msg,int attrtype,struct nl_msg * nested)778 int nla_put_nested(struct nl_msg *msg, int attrtype, struct nl_msg *nested)
779 {
780 	NL_DBG(2, "msg %p: attr <> %d: adding msg %p as nested attribute\n",
781 		msg, attrtype, nested);
782 
783 	return nla_put(msg, attrtype, nlmsg_datalen(nested->nm_nlh),
784 		       nlmsg_data(nested->nm_nlh));
785 }
786 
787 
788 /**
789  * Start a new level of nested attributes.
790  * @arg msg		Netlink message.
791  * @arg attrtype	Attribute type of container.
792  *
793  * @return Pointer to container attribute.
794  */
nla_nest_start(struct nl_msg * msg,int attrtype)795 struct nlattr *nla_nest_start(struct nl_msg *msg, int attrtype)
796 {
797 	struct nlattr *start = (struct nlattr *) nlmsg_tail(msg->nm_nlh);
798 
799 	if (nla_put(msg, NLA_F_NESTED | attrtype, 0, NULL) < 0)
800 		return NULL;
801 
802 	NL_DBG(2, "msg %p: attr <%p> %d: starting nesting\n",
803 		msg, start, start->nla_type);
804 
805 	return start;
806 }
807 
808 /**
809  * Finalize nesting of attributes.
810  * @arg msg		Netlink message.
811  * @arg start		Container attribute as returned from nla_nest_start().
812  *
813  * Corrects the container attribute header to include the appeneded attributes.
814  *
815  * @return 0
816  */
nla_nest_end(struct nl_msg * msg,struct nlattr * start)817 int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
818 {
819 	size_t pad, len;
820 
821 	len = (void *) nlmsg_tail(msg->nm_nlh) - (void *) start;
822 
823 	if (len == NLA_HDRLEN) {
824 		/*
825 		 * Kernel can't handle empty nested attributes, trim the
826 		 * attribute header again
827 		 */
828 		nla_nest_cancel(msg, start);
829 
830 		return 0;
831 	}
832 
833 	start->nla_len = len;
834 
835 	pad = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) - msg->nm_nlh->nlmsg_len;
836 	if (pad > 0) {
837 		/*
838 		 * Data inside attribute does not end at a alignment boundry.
839 		 * Pad accordingly and accoun for the additional space in
840 		 * the message. nlmsg_reserve() may never fail in this situation,
841 		 * the allocate message buffer must be a multiple of NLMSG_ALIGNTO.
842 		 */
843 		if (!nlmsg_reserve(msg, pad, 0))
844 			BUG();
845 
846 		NL_DBG(2, "msg %p: attr <%p> %d: added %zu bytes of padding\n",
847 			msg, start, start->nla_type, pad);
848 	}
849 
850 	NL_DBG(2, "msg %p: attr <%p> %d: closing nesting, len=%u\n",
851 		msg, start, start->nla_type, start->nla_len);
852 
853 	return 0;
854 }
855 
856 /**
857  * Cancel the addition of a nested attribute
858  * @arg msg		Netlink message
859  * @arg attr		Nested netlink attribute
860  *
861  * Removes any partially added nested Netlink attribute from the message
862  * by resetting the message to the size before the call to nla_nest_start()
863  * and by overwriting any potentially touched message segments with 0.
864  */
nla_nest_cancel(struct nl_msg * msg,struct nlattr * attr)865 void nla_nest_cancel(struct nl_msg *msg, struct nlattr *attr)
866 {
867 	ssize_t len;
868 
869 	len = (void *) nlmsg_tail(msg->nm_nlh) - (void *) attr;
870 	if (len < 0)
871 		BUG();
872 	else if (len > 0) {
873 		msg->nm_nlh->nlmsg_len -= len;
874 		memset(nlmsg_tail(msg->nm_nlh), 0, len);
875 	}
876 }
877 
878 /**
879  * Create attribute index based on nested attribute
880  * @arg tb		Index array to be filled (maxtype+1 elements).
881  * @arg maxtype		Maximum attribute type expected and accepted.
882  * @arg nla		Nested Attribute.
883  * @arg policy		Attribute validation policy.
884  *
885  * Feeds the stream of attributes nested into the specified attribute
886  * to nla_parse().
887  *
888  * @see nla_parse
889  * @return 0 on success or a negative error code.
890  */
nla_parse_nested(struct nlattr * tb[],int maxtype,struct nlattr * nla,struct nla_policy * policy)891 int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla,
892 		     struct nla_policy *policy)
893 {
894 	return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
895 }
896 
897 /**
898  * Return true if attribute has NLA_F_NESTED flag set
899  * @arg attr		Netlink attribute
900  *
901  * @return True if attribute has NLA_F_NESTED flag set, oterhwise False.
902  */
nla_is_nested(struct nlattr * attr)903 int nla_is_nested(struct nlattr *attr)
904 {
905 	return !!(attr->nla_type & NLA_F_NESTED);
906 }
907 
908 /** @} */
909 
910 /** @} */
911