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