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