libnl  1.1
attr.c
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-2006 Thomas Graf <tgraf@suug.ch>
10  */
11 
12 #include <netlink-local.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  * @par 0) Introduction
25  * Netlink attributes are chained together following each other:
26  * @code
27  * <------- nla_total_size(payload) ------->
28  * <---- nla_attr_size(payload) ----->
29  * +----------+- - -+- - - - - - - - - +- - -+-------- - -
30  * | Header | Pad | Payload | Pad | Header
31  * +----------+- - -+- - - - - - - - - +- - -+-------- - -
32  * <- nla_len(nla) -> ^
33  * nla_data(nla)----^ |
34  * nla_next(nla)-----------------------------'
35  * @endcode
36  *
37  * @par
38  * The attribute header and payload must be aligned properly:
39  * @code
40  * <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
41  * +---------------------+- - -+- - - - - - - - - -+- - -+
42  * | Header | Pad | Payload | Pad |
43  * | (struct nlattr) | ing | | ing |
44  * +---------------------+- - -+- - - - - - - - - -+- - -+
45  * <-------------- nlattr->nla_len -------------->
46  * @endcode
47  *
48  * @par Nested TLVs:
49  * Nested TLVs are an array of TLVs nested into another TLV. This can be useful
50  * to allow subsystems to have their own formatting rules without the need to
51  * make the underlying layer be aware of it. It can also be useful to transfer
52  * arrays, lists and flattened trees.
53  * \code
54  * <-------------------- NLA_ALIGN(...) ------------------->
55  * +---------------+- - - - - - - - - - - - - - - - - -+- - -+
56  * | |+---------+---------+- - -+-------+| |
57  * | TLV Header || TLV 1 | TLV 2 | | TLV n || Pad |
58  * | |+---------+---------+- - -+-------+| |
59  * +---------------+- - - - - - - - - - - - - - - - - -+- - -+
60  * <--------- nla_data(nla) --------->
61  * \endcode
62  *
63  * @par 1) Constructing a message with attributes
64  * @code
65  * int param1 = 10;
66  * char *param2 = "parameter text";
67  *
68  * struct nl_msg *msg = nlmsg_alloc();
69  * nla_put_u32(msg, 1, param1);
70  * nla_put_string(msg, 2, param2);
71  *
72  * nl_send_auto_complete(handle, nl_msg_get(msg));
73  * nlmsg_free(msg);
74  * @endcode
75  *
76  * @par 2) Constructing nested attributes
77  * @code
78  * struct nl_msg * nested_config(void)
79  * {
80  * int a = 5, int b = 10;
81  * struct nl_msg *n = nlmsg_alloc();
82  * nla_put_u32(n, 10, a);
83  * nla_put_u32(n, 20, b);
84  * return n;
85  * }
86  *
87  * ...
88  * struct nl_msg *m = nlmsg_alloc();
89  * struct nl_msg *nest = nested_config();
90  * nla_put_nested(m, 1, nest);
91  *
92  * nl_send_auto_complete(handle, nl_msg_get(m));
93  * nlmsg_free(nest);
94  * nlmsg_free(m);
95  * @endcode
96  * @{
97  */
98 
99 /**
100  * @name Size Calculations
101  * @{
102  */
103 
104 /**
105  * length of attribute not including padding
106  * @arg payload length of payload
107  */
108 int nla_attr_size(int payload)
109 {
110  return NLA_HDRLEN + payload;
111 }
112 
113 /**
114  * total length of attribute including padding
115  * @arg payload length of payload
116  */
117 int nla_total_size(int payload)
118 {
119  return NLA_ALIGN(nla_attr_size(payload));
120 }
121 
122 /**
123  * length of padding at the tail of the attribute
124  * @arg payload length of payload
125  */
126 int nla_padlen(int payload)
127 {
128  return nla_total_size(payload) - nla_attr_size(payload);
129 }
130 
131 /** @} */
132 
133 /**
134  * @name Payload Access
135  * @{
136  */
137 
138 /**
139  * attribute type
140  * @arg nla netlink attribute
141  */
142 int nla_type(const struct nlattr *nla)
143 {
144  return nla->nla_type & NLA_TYPE_MASK;
145 }
146 
147 /**
148  * head of payload
149  * @arg nla netlink attribute
150  */
151 void *nla_data(const struct nlattr *nla)
152 {
153  return (char *) nla + NLA_HDRLEN;
154 }
155 
156 /**
157  * length of payload
158  * @arg nla netlink attribute
159  */
160 int nla_len(const struct nlattr *nla)
161 {
162  return nla->nla_len - NLA_HDRLEN;
163 }
164 
165 /** @} */
166 
167 /**
168  * @name Attribute Parsing
169  * @{
170  */
171 
172 /**
173  * check if the netlink attribute fits into the remaining bytes
174  * @arg nla netlink attribute
175  * @arg remaining number of bytes remaining in attribute stream
176  */
177 int nla_ok(const struct nlattr *nla, int remaining)
178 {
179  return remaining >= sizeof(*nla) &&
180  nla->nla_len >= sizeof(*nla) &&
181  nla->nla_len <= remaining;
182 }
183 
184 /**
185  * next netlink attribte in attribute stream
186  * @arg nla netlink attribute
187  * @arg remaining number of bytes remaining in attribute stream
188  *
189  * @return the next netlink attribute in the attribute stream and
190  * decrements remaining by the size of the current attribute.
191  */
192 struct nlattr *nla_next(const struct nlattr *nla, int *remaining)
193 {
194  int totlen = NLA_ALIGN(nla->nla_len);
195 
196  *remaining -= totlen;
197  return (struct nlattr *) ((char *) nla + totlen);
198 }
199 
200 static uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = {
201  [NLA_U8] = sizeof(uint8_t),
202  [NLA_U16] = sizeof(uint16_t),
203  [NLA_U32] = sizeof(uint32_t),
204  [NLA_U64] = sizeof(uint64_t),
205  [NLA_STRING] = 1,
206  [NLA_NESTED] = NLA_HDRLEN,
207 };
208 
209 static int validate_nla(struct nlattr *nla, int maxtype,
210  struct nla_policy *policy)
211 {
212  struct nla_policy *pt;
213  int minlen = 0, type = nla_type(nla);
214 
215  if (type <= 0 || type > maxtype)
216  return 0;
217 
218  pt = &policy[type];
219 
220  if (pt->type > NLA_TYPE_MAX)
221  BUG();
222 
223  if (pt->minlen)
224  minlen = pt->minlen;
225  else if (pt->type != NLA_UNSPEC)
226  minlen = nla_attr_minlen[pt->type];
227 
228  if (pt->type == NLA_FLAG && nla_len(nla) > 0)
229  return nl_errno(ERANGE);
230 
231  if (nla_len(nla) < minlen)
232  return nl_errno(ERANGE);
233 
234  if (pt->maxlen && nla_len(nla) > pt->maxlen)
235  return nl_errno(ERANGE);
236 
237  if (pt->type == NLA_STRING) {
238  char *data = nla_data(nla);
239  if (data[nla_len(nla) - 1] != '\0')
240  return nl_errno(EINVAL);
241  }
242 
243  return 0;
244 }
245 
246 
247 /**
248  * Parse a stream of attributes into a tb buffer
249  * @arg tb destination array with maxtype+1 elements
250  * @arg maxtype maximum attribute type to be expected
251  * @arg head head of attribute stream
252  * @arg len length of attribute stream
253  * @arg policy validation policy
254  *
255  * Parses a stream of attributes and stores a pointer to each attribute in
256  * the tb array accessable via the attribute type. Attributes with a type
257  * exceeding maxtype will be silently ignored for backwards compatibility
258  * reasons. policy may be set to NULL if no validation is required.
259  *
260  * @return 0 on success or a negative error code.
261  */
262 int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
263  struct nla_policy *policy)
264 {
265  struct nlattr *nla;
266  int rem, err;
267 
268  memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
269 
270  nla_for_each_attr(nla, head, len, rem) {
271  int type = nla_type(nla);
272 
273  if (type == 0) {
274  fprintf(stderr, "Illegal nla->nla_type == 0\n");
275  continue;
276  }
277 
278  if (type <= maxtype) {
279  if (policy) {
280  err = validate_nla(nla, maxtype, policy);
281  if (err < 0)
282  goto errout;
283  }
284 
285  tb[type] = nla;
286  }
287  }
288 
289  if (rem > 0)
290  fprintf(stderr, "netlink: %d bytes leftover after parsing "
291  "attributes.\n", rem);
292 
293  err = 0;
294 errout:
295  return err;
296 }
297 
298 
299 /**
300  * parse nested attributes
301  * @arg tb destination array with maxtype+1 elements
302  * @arg maxtype maximum attribute type to be expected
303  * @arg nla attribute containing the nested attributes
304  * @arg policy validation policy
305  *
306  * @see nla_parse()
307  */
308 int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla,
309  struct nla_policy *policy)
310 {
311  return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
312 }
313 
314 /**
315  * Validate a stream of attributes
316  * @arg head head of attribute stream
317  * @arg len length of attribute stream
318  * @arg maxtype maximum attribute type to be expected
319  * @arg policy validation policy
320  *
321  * Validates all attributes in the specified attribute stream
322  * against the specified policy. Attributes with a type exceeding
323  * maxtype will be ignored. See documenation of struct nla_policy
324  * for more details.
325  *
326  * @return 0 on success or a negative error code.
327  */
328 int nla_validate(struct nlattr *head, int len, int maxtype,
329  struct nla_policy *policy)
330 {
331  struct nlattr *nla;
332  int rem, err;
333 
334  nla_for_each_attr(nla, head, len, rem) {
335  err = validate_nla(nla, maxtype, policy);
336  if (err < 0)
337  goto errout;
338  }
339 
340  err = 0;
341 errout:
342  return err;
343 }
344 
345 /**
346  * Find a specific attribute in a stream of attributes
347  * @arg head head of attribute stream
348  * @arg len length of attribute stream
349  * @arg attrtype type of attribute to look for
350  *
351  * @return the first attribute in the stream matching the specified type.
352  */
353 struct nlattr *nla_find(struct nlattr *head, int len, int attrtype)
354 {
355  struct nlattr *nla;
356  int rem;
357 
358  nla_for_each_attr(nla, head, len, rem)
359  if (nla_type(nla) == attrtype)
360  return nla;
361 
362  return NULL;
363 }
364 
365 /** @} */
366 
367 /**
368  * @name Utilities
369  * @{
370  */
371 
372 /**
373  * Copy a netlink attribute into another memory area
374  * @arg dest where to copy to memcpy
375  * @arg src netlink attribute to copy from
376  * @arg count size of the destination area
377  *
378  * Note: The number of bytes copied is limited by the length of
379  * attribute's payload. memcpy
380  *
381  * @return the number of bytes copied.
382  */
383 int nla_memcpy(void *dest, struct nlattr *src, int count)
384 {
385  int minlen;
386 
387  if (!src)
388  return 0;
389 
390  minlen = min_t(int, count, nla_len(src));
391  memcpy(dest, nla_data(src), minlen);
392 
393  return minlen;
394 }
395 
396 /**
397  * Copy string attribute payload into a sized buffer
398  * @arg dst where to copy the string to
399  * @arg nla attribute to copy the string from
400  * @arg dstsize size of destination buffer
401  *
402  * Copies at most dstsize - 1 bytes into the destination buffer.
403  * The result is always a valid NUL-terminated string. Unlike
404  * strlcpy the destination buffer is always padded out.
405  *
406  * @return the length of the source buffer.
407  */
408 size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
409 {
410  size_t srclen = nla_len(nla);
411  char *src = nla_data(nla);
412 
413  if (srclen > 0 && src[srclen - 1] == '\0')
414  srclen--;
415 
416  if (dstsize > 0) {
417  size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
418 
419  memset(dst, 0, dstsize);
420  memcpy(dst, src, len);
421  }
422 
423  return srclen;
424 }
425 
426 /**
427  * Compare an attribute with sized memory area
428  * @arg nla netlink attribute
429  * @arg data memory area
430  * @arg size size of memory area
431  */
432 int nla_memcmp(const struct nlattr *nla, const void *data,
433  size_t size)
434 {
435  int d = nla_len(nla) - size;
436 
437  if (d == 0)
438  d = memcmp(nla_data(nla), data, size);
439 
440  return d;
441 }
442 
443 /**
444  * Compare a string attribute against a string
445  * @arg nla netlink string attribute
446  * @arg str another string
447  */
448 int nla_strcmp(const struct nlattr *nla, const char *str)
449 {
450  int len = strlen(str) + 1;
451  int d = nla_len(nla) - len;
452 
453  if (d == 0)
454  d = memcmp(nla_data(nla), str, len);
455 
456  return d;
457 }
458 
459 /** @} */
460 
461 /**
462  * @name Attribute Construction
463  * @{
464  */
465 
466 /**
467  * reserve room for attribute on the skb
468  * @arg n netlink message
469  * @arg attrtype attribute type
470  * @arg attrlen length of attribute payload
471  *
472  * Adds a netlink attribute header to a netlink message and reserves
473  * room for the payload but does not copy it.
474  */
475 struct nlattr *nla_reserve(struct nl_msg *n, int attrtype, int attrlen)
476 {
477  struct nlattr *nla;
478  int tlen;
479 
480  tlen = NLMSG_ALIGN(n->nm_nlh->nlmsg_len) + nla_total_size(attrlen);
481 
482  if ((tlen + n->nm_nlh->nlmsg_len) > n->nm_size) {
483  nl_errno(ENOBUFS);
484  return NULL;
485  }
486 
487  nla = (struct nlattr *) nlmsg_tail(n->nm_nlh);
488  nla->nla_type = attrtype;
489  nla->nla_len = nla_attr_size(attrlen);
490 
491  memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen));
492  n->nm_nlh->nlmsg_len = tlen;
493 
494  NL_DBG(2, "msg %p: Reserved %d bytes at offset +%td for attr %d "
495  "nlmsg_len=%d\n", n, attrlen,
496  (void *) nla - nlmsg_data(n->nm_nlh),
497  attrtype, n->nm_nlh->nlmsg_len);
498 
499  return nla;
500 }
501 
502 /**
503  * Add a netlink attribute to a netlink message
504  * @arg n netlink message
505  * @arg attrtype attribute type
506  * @arg attrlen length of attribute payload
507  * @arg data head of attribute payload
508  *
509  * @return -1 if the tailroom of the skb is insufficient to store
510  * the attribute header and payload.
511  */
512 int nla_put(struct nl_msg *n, int attrtype, int attrlen, const void *data)
513 {
514  struct nlattr *nla;
515 
516  nla = nla_reserve(n, attrtype, attrlen);
517  if (!nla)
518  return nl_errno(ENOMEM);
519 
520  memcpy(nla_data(nla), data, attrlen);
521  NL_DBG(2, "msg %p: Wrote %d bytes at offset +%td for attr %d\n",
522  n, attrlen, (void *) nla - nlmsg_data(n->nm_nlh), attrtype);
523 
524  return 0;
525 }
526 
527 /**
528  * Add a nested netlink attribute to a netlink message
529  * @arg n netlink message
530  * @arg attrtype attribute type
531  * @arg nested netlink attribute to nest
532  *
533  * @return -1 if the tailroom of the skb is insufficient to store
534  * the attribute header and payload.
535  */
536 int nla_put_nested(struct nl_msg *n, int attrtype, struct nl_msg *nested)
537 {
538  return nla_put(n, attrtype, nlmsg_len(nested->nm_nlh),
539  nlmsg_data(nested->nm_nlh));
540 }
541 
542 /**
543  * Add a u16 netlink attribute to a netlink message
544  * @arg n netlink message
545  * @arg attrtype attribute type
546  * @arg value numeric value
547  */
548 int nla_put_u8(struct nl_msg *n, int attrtype, uint8_t value)
549 {
550  return nla_put(n, attrtype, sizeof(uint8_t), &value);
551 }
552 
553 /**
554  * Add a u16 netlink attribute to a netlink message
555  * @arg n netlink message
556  * @arg attrtype attribute type
557  * @arg value numeric value
558  */
559 int nla_put_u16(struct nl_msg *n, int attrtype, uint16_t value)
560 {
561  return nla_put(n, attrtype, sizeof(uint16_t), &value);
562 }
563 
564 /**
565  * Add a u32 netlink attribute to a netlink message
566  * @arg n netlink message
567  * @arg attrtype attribute type
568  * @arg value numeric value
569  */
570 int nla_put_u32(struct nl_msg *n, int attrtype, uint32_t value)
571 {
572  return nla_put(n, attrtype, sizeof(uint32_t), &value);
573 }
574 
575 /**
576  * Add a u64 netlink attribute to a netlink message
577  * @arg n netlink message
578  * @arg attrtype attribute type
579  * @arg value numeric value
580  */
581 int nla_put_u64(struct nl_msg *n, int attrtype, uint64_t value)
582 {
583  return nla_put(n, attrtype, sizeof(uint64_t), &value);
584 }
585 
586 /**
587  * Add a string netlink attribute to a netlink message
588  * @arg n netlink message
589  * @arg attrtype attribute type
590  * @arg str NUL terminated string
591  */
592 int nla_put_string(struct nl_msg *n, int attrtype, const char *str)
593 {
594  return nla_put(n, attrtype, strlen(str) + 1, str);
595 }
596 
597 /**
598  * Add a flag netlink attribute to a netlink message
599  * @arg n netlink message
600  * @arg attrtype attribute type
601  */
602 int nla_put_flag(struct nl_msg *n, int attrtype)
603 {
604  return nla_put(n, attrtype, 0, NULL);
605 }
606 
607 /**
608  * Add a msecs netlink attribute to a netlink message
609  * @arg n netlink message
610  * @arg attrtype attribute type
611  * @arg msecs number of msecs
612  */
613 int nla_put_msecs(struct nl_msg *n, int attrtype, unsigned long msecs)
614 {
615  return nla_put_u64(n, attrtype, msecs);
616 }
617 
618 /**
619  * Add an abstract data netlink attribute to a netlink message
620  * @arg n netlink message
621  * @arg attrtype attribute type
622  * @arg data abstract data
623  */
624 int nla_put_data(struct nl_msg *n, int attrtype, struct nl_data *data)
625 {
626  return nla_put(n, attrtype, nl_data_get_size(data),
627  nl_data_get(data));
628 }
629 
630 /**
631  * Add an abstract address netlink attribute to a netlink message
632  * @arg n netlink message
633  * @arg attrtype attribute type
634  * @arg addr abstract address
635  */
636 int nla_put_addr(struct nl_msg *n, int attrtype, struct nl_addr *addr)
637 {
638  return nla_put(n, attrtype, nl_addr_get_len(addr),
640 }
641 
642 /** @} */
643 
644 /**
645  * @name Attribute Nesting
646  * @{
647  */
648 
649 /**
650  * Start a new level of nested attributes
651  * @arg n netlink message
652  * @arg attrtype attribute type of container
653  *
654  * @return the container attribute
655  */
656 struct nlattr *nla_nest_start(struct nl_msg *n, int attrtype)
657 {
658  struct nlattr *start = (struct nlattr *) nlmsg_tail(n->nm_nlh);
659 
660  if (nla_put(n, attrtype, 0, NULL) < 0)
661  return NULL;
662 
663  return start;
664 }
665 
666 /**
667  * Finalize nesting of attributes
668  * @arg n netlink message
669  * @arg start container attribute
670  *
671  * Corrects the container attribute header to include the all
672  * appeneded attributes.
673  *
674  * @return the total data length of the skb.
675  */
676 int nla_nest_end(struct nl_msg *n, struct nlattr *start)
677 {
678  start->nla_len = (unsigned char *) nlmsg_tail(n->nm_nlh) -
679  (unsigned char *) start;
680  return 0;
681 }
682 
683 /** @} */
684 
685 /**
686  * @name Attribute Reading
687  * @{
688  */
689 
690 /**
691  * Return payload of u32 attribute
692  * @arg nla u32 netlink attribute
693  */
694 uint32_t nla_get_u32(struct nlattr *nla)
695 {
696  return *(uint32_t *) nla_data(nla);
697 }
698 
699 /**
700  * Return payload of u16 attribute
701  * @arg nla u16 netlink attribute
702  */
703 uint16_t nla_get_u16(struct nlattr *nla)
704 {
705  return *(uint16_t *) nla_data(nla);
706 }
707 
708 /**
709  * Return payload of u8 attribute
710  * @arg nla u8 netlink attribute
711  */
712 uint8_t nla_get_u8(struct nlattr *nla)
713 {
714  return *(uint8_t *) nla_data(nla);
715 }
716 
717 /**
718  * Return payload of u64 attribute
719  * @arg nla u64 netlink attribute
720  */
721 uint64_t nla_get_u64(struct nlattr *nla)
722 {
723  uint64_t tmp;
724 
725  nla_memcpy(&tmp, nla, sizeof(tmp));
726 
727  return tmp;
728 }
729 
730 /**
731  * return payload of string attribute
732  * @arg nla string netlink attribute
733  */
734 char *nla_get_string(struct nlattr *nla)
735 {
736  return (char *) nla_data(nla);
737 }
738 
739 /**
740  * Return payload of flag attribute
741  * @arg nla flag netlink attribute
742  */
743 int nla_get_flag(struct nlattr *nla)
744 {
745  return !!nla;
746 }
747 
748 /**
749  * Return payload of msecs attribute
750  * @arg nla msecs netlink attribute
751  *
752  * @return the number of milliseconds.
753  */
754 unsigned long nla_get_msecs(struct nlattr *nla)
755 {
756  return nla_get_u64(nla);
757 }
758 
759 /**
760  * Return payload of address attribute
761  * @arg nla address netlink attribute
762  * @arg family address family
763  *
764  * @return Newly allocated address handle or NULL
765  */
766 struct nl_addr *nla_get_addr(struct nlattr *nla, int family)
767 {
768  return nl_addr_build(family, nla_data(nla), nla_len(nla));
769 }
770 
771 /**
772  * Return payload of abstract data attribute
773  * @arg nla abstract data netlink attribute
774  *
775  * @return Newly allocated abstract data handle or NULL
776  */
777 struct nl_data *nla_get_data(struct nlattr *nla)
778 {
779  return nl_data_alloc(nla_data(nla), nla_len(nla));
780 }
781 
782 /** @} */
783 
784 /** @} */