move library packages to package/libs/
[openwrt.git] / package / libs / libnl-tiny / src / include / netlink / attr.h
1 /*
2  * netlink/attr.h               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-2008 Thomas Graf <tgraf@suug.ch>
10  */
11
12 #ifndef NETLINK_ATTR_H_
13 #define NETLINK_ATTR_H_
14
15 #include <netlink/netlink.h>
16 #include <netlink/object.h>
17 #include <netlink/addr.h>
18 #include <netlink/data.h>
19 #include <netlink/msg.h>
20
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24
25 struct nl_msg;
26
27 /**
28  * @name Basic Attribute Data Types
29  * @{
30  */
31
32  /**
33   * @ingroup attr
34   * Basic attribute data types
35   *
36   * See \ref attr_datatypes for more details.
37   */
38 enum {
39         NLA_UNSPEC,     /**< Unspecified type, binary data chunk */
40         NLA_U8,         /**< 8 bit integer */
41         NLA_U16,        /**< 16 bit integer */
42         NLA_U32,        /**< 32 bit integer */
43         NLA_U64,        /**< 64 bit integer */
44         NLA_STRING,     /**< NUL terminated character string */
45         NLA_FLAG,       /**< Flag */
46         NLA_MSECS,      /**< Micro seconds (64bit) */
47         NLA_NESTED,     /**< Nested attributes */
48         __NLA_TYPE_MAX,
49 };
50
51 #define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1)
52
53 /** @} */
54
55 /**
56  * @ingroup attr
57  * Attribute validation policy.
58  *
59  * See \ref attr_datatypes for more details.
60  */
61 struct nla_policy {
62         /** Type of attribute or NLA_UNSPEC */
63         uint16_t        type;
64
65         /** Minimal length of payload required */
66         uint16_t        minlen;
67
68         /** Maximal length of payload allowed */
69         uint16_t        maxlen;
70 };
71
72 /* Attribute parsing */
73 extern int              nla_ok(const struct nlattr *, int);
74 extern struct nlattr *  nla_next(const struct nlattr *, int *);
75 extern int              nla_parse(struct nlattr **, int, struct nlattr *,
76                                   int, struct nla_policy *);
77 extern int              nla_validate(struct nlattr *, int, int,
78                                      struct nla_policy *);
79 extern struct nlattr *  nla_find(struct nlattr *, int, int);
80
81 /* Unspecific attribute */
82 extern struct nlattr *  nla_reserve(struct nl_msg *, int, int);
83 extern int              nla_put(struct nl_msg *, int, int, const void *);
84
85 /**
86  * nlmsg_find_attr - find a specific attribute in a netlink message
87  * @arg nlh             netlink message header
88  * @arg hdrlen          length of familiy specific header
89  * @arg attrtype        type of attribute to look for
90  *
91  * Returns the first attribute which matches the specified type.
92  */
93 static inline struct nlattr *nlmsg_find_attr(struct nlmsghdr *nlh, int hdrlen, int attrtype)
94 {
95         return nla_find(nlmsg_attrdata(nlh, hdrlen),
96                         nlmsg_attrlen(nlh, hdrlen), attrtype);
97 }
98
99
100 /**
101  * Return size of attribute whithout padding.
102  * @arg payload         Payload length of attribute.
103  *
104  * @code
105  *    <-------- nla_attr_size(payload) --------->
106  *   +------------------+- - -+- - - - - - - - - +- - -+
107  *   | Attribute Header | Pad |     Payload      | Pad |
108  *   +------------------+- - -+- - - - - - - - - +- - -+
109  * @endcode
110  *
111  * @return Size of attribute in bytes without padding.
112  */
113 static inline int nla_attr_size(int payload)
114 {
115         return NLA_HDRLEN + payload;
116 }
117
118 /**
119  * Return size of attribute including padding.
120  * @arg payload         Payload length of attribute.
121  *
122  * @code
123  *    <----------- nla_total_size(payload) ----------->
124  *   +------------------+- - -+- - - - - - - - - +- - -+
125  *   | Attribute Header | Pad |     Payload      | Pad |
126  *   +------------------+- - -+- - - - - - - - - +- - -+
127  * @endcode
128  *
129  * @return Size of attribute in bytes.
130  */
131 static inline int nla_total_size(int payload)
132 {
133         return NLA_ALIGN(nla_attr_size(payload));
134 }
135
136 /**
137  * Return length of padding at the tail of the attribute.
138  * @arg payload         Payload length of attribute.
139  *
140  * @code
141  *   +------------------+- - -+- - - - - - - - - +- - -+
142  *   | Attribute Header | Pad |     Payload      | Pad |
143  *   +------------------+- - -+- - - - - - - - - +- - -+
144  *                                                <--->  
145  * @endcode
146  *
147  * @return Length of padding in bytes.
148  */
149 static inline int nla_padlen(int payload)
150 {
151         return nla_total_size(payload) - nla_attr_size(payload);
152 }
153
154 /**
155  * Return type of the attribute.
156  * @arg nla             Attribute.
157  *
158  * @return Type of attribute.
159  */
160 static inline int nla_type(const struct nlattr *nla)
161 {
162         return nla->nla_type & NLA_TYPE_MASK;
163 }
164
165 /**
166  * Return pointer to the payload section.
167  * @arg nla             Attribute.
168  *
169  * @return Pointer to start of payload section.
170  */
171 static inline void *nla_data(const struct nlattr *nla)
172 {
173         return (char *) nla + NLA_HDRLEN;
174 }
175
176 /**
177  * Return length of the payload .
178  * @arg nla             Attribute
179  *
180  * @return Length of payload in bytes.
181  */
182 static inline int nla_len(const struct nlattr *nla)
183 {
184         return nla->nla_len - NLA_HDRLEN;
185 }
186
187 /**
188  * Copy attribute payload to another memory area.
189  * @arg dest            Pointer to destination memory area.
190  * @arg src             Attribute
191  * @arg count           Number of bytes to copy at most.
192  *
193  * Note: The number of bytes copied is limited by the length of
194  *       the attribute payload.
195  *
196  * @return The number of bytes copied to dest.
197  */
198 static inline int nla_memcpy(void *dest, struct nlattr *src, int count)
199 {
200         int minlen;
201
202         if (!src)
203                 return 0;
204         
205         minlen = min_t(int, count, nla_len(src));
206         memcpy(dest, nla_data(src), minlen);
207
208         return minlen;
209 }
210
211
212 /**
213  * Add abstract data as unspecific attribute to netlink message.
214  * @arg msg             Netlink message.
215  * @arg attrtype        Attribute type.
216  * @arg data            Abstract data object.
217  *
218  * Equivalent to nla_put() except that the length of the payload is
219  * derived from the abstract data object.
220  *
221  * @see nla_put
222  * @return 0 on success or a negative error code.
223  */
224 static inline int nla_put_data(struct nl_msg *msg, int attrtype, struct nl_data *data)
225 {
226         return nla_put(msg, attrtype, nl_data_get_size(data),
227                        nl_data_get(data));
228 }
229
230 /**
231  * Add abstract address as unspecific attribute to netlink message.
232  * @arg msg             Netlink message.
233  * @arg attrtype        Attribute type.
234  * @arg addr            Abstract address object.
235  *
236  * @see nla_put
237  * @return 0 on success or a negative error code.
238  */
239 static inline int nla_put_addr(struct nl_msg *msg, int attrtype, struct nl_addr *addr)
240 {
241         return nla_put(msg, attrtype, nl_addr_get_len(addr),
242                        nl_addr_get_binary_addr(addr));
243 }
244
245 /** @} */
246
247 /**
248  * @name Integer Attributes
249  */
250
251 /**
252  * Add 8 bit integer attribute to netlink message.
253  * @arg msg             Netlink message.
254  * @arg attrtype        Attribute type.
255  * @arg value           Numeric value to store as payload.
256  *
257  * @see nla_put
258  * @return 0 on success or a negative error code.
259  */
260 static inline int nla_put_u8(struct nl_msg *msg, int attrtype, uint8_t value)
261 {
262         return nla_put(msg, attrtype, sizeof(uint8_t), &value);
263 }
264
265 /**
266  * Return value of 8 bit integer attribute.
267  * @arg nla             8 bit integer attribute
268  *
269  * @return Payload as 8 bit integer.
270  */
271 static inline uint8_t nla_get_u8(struct nlattr *nla)
272 {
273         return *(uint8_t *) nla_data(nla);
274 }
275
276 /**
277  * Add 16 bit integer attribute to netlink message.
278  * @arg msg             Netlink message.
279  * @arg attrtype        Attribute type.
280  * @arg value           Numeric value to store as payload.
281  *
282  * @see nla_put
283  * @return 0 on success or a negative error code.
284  */
285 static inline int nla_put_u16(struct nl_msg *msg, int attrtype, uint16_t value)
286 {
287         return nla_put(msg, attrtype, sizeof(uint16_t), &value);
288 }
289
290 /**
291  * Return payload of 16 bit integer attribute.
292  * @arg nla             16 bit integer attribute
293  *
294  * @return Payload as 16 bit integer.
295  */
296 static inline uint16_t nla_get_u16(struct nlattr *nla)
297 {
298         return *(uint16_t *) nla_data(nla);
299 }
300
301 /**
302  * Add 32 bit integer attribute to netlink message.
303  * @arg msg             Netlink message.
304  * @arg attrtype        Attribute type.
305  * @arg value           Numeric value to store as payload.
306  *
307  * @see nla_put
308  * @return 0 on success or a negative error code.
309  */
310 static inline int nla_put_u32(struct nl_msg *msg, int attrtype, uint32_t value)
311 {
312         return nla_put(msg, attrtype, sizeof(uint32_t), &value);
313 }
314
315 /**
316  * Return payload of 32 bit integer attribute.
317  * @arg nla             32 bit integer attribute.
318  *
319  * @return Payload as 32 bit integer.
320  */
321 static inline uint32_t nla_get_u32(struct nlattr *nla)
322 {
323         return *(uint32_t *) nla_data(nla);
324 }
325
326 /**
327  * Add 64 bit integer attribute to netlink message.
328  * @arg msg             Netlink message.
329  * @arg attrtype        Attribute type.
330  * @arg value           Numeric value to store as payload.
331  *
332  * @see nla_put
333  * @return 0 on success or a negative error code.
334  */
335 static inline int nla_put_u64(struct nl_msg *msg, int attrtype, uint64_t value)
336 {
337         return nla_put(msg, attrtype, sizeof(uint64_t), &value);
338 }
339
340 /**
341  * Return payload of u64 attribute
342  * @arg nla             u64 netlink attribute
343  *
344  * @return Payload as 64 bit integer.
345  */
346 static inline uint64_t nla_get_u64(struct nlattr *nla)
347 {
348         uint64_t tmp;
349
350         nla_memcpy(&tmp, nla, sizeof(tmp));
351
352         return tmp;
353 }
354
355 /**
356  * Add string attribute to netlink message.
357  * @arg msg             Netlink message.
358  * @arg attrtype        Attribute type.
359  * @arg str             NUL terminated string.
360  *
361  * @see nla_put
362  * @return 0 on success or a negative error code.
363  */
364 static inline int nla_put_string(struct nl_msg *msg, int attrtype, const char *str)
365 {
366         return nla_put(msg, attrtype, strlen(str) + 1, str);
367 }
368
369 /**
370  * Return payload of string attribute.
371  * @arg nla             String attribute.
372  *
373  * @return Pointer to attribute payload.
374  */
375 static inline char *nla_get_string(struct nlattr *nla)
376 {
377         return (char *) nla_data(nla);
378 }
379
380 static inline char *nla_strdup(struct nlattr *nla)
381 {
382         return strdup(nla_get_string(nla));
383 }
384
385 /** @} */
386
387 /**
388  * @name Flag Attribute
389  */
390
391 /**
392  * Add flag netlink attribute to netlink message.
393  * @arg msg             Netlink message.
394  * @arg attrtype        Attribute type.
395  *
396  * @see nla_put
397  * @return 0 on success or a negative error code.
398  */
399 static inline int nla_put_flag(struct nl_msg *msg, int attrtype)
400 {
401         return nla_put(msg, attrtype, 0, NULL);
402 }
403
404 /**
405  * Return true if flag attribute is set.
406  * @arg nla             Flag netlink attribute.
407  *
408  * @return True if flag is set, otherwise false.
409  */
410 static inline int nla_get_flag(struct nlattr *nla)
411 {
412         return !!nla;
413 }
414
415 /** @} */
416
417 /**
418  * @name Microseconds Attribute
419  */
420
421 /**
422  * Add a msecs netlink attribute to a netlink message
423  * @arg n               netlink message
424  * @arg attrtype        attribute type
425  * @arg msecs           number of msecs
426  */
427 static inline int nla_put_msecs(struct nl_msg *n, int attrtype, unsigned long msecs)
428 {
429         return nla_put_u64(n, attrtype, msecs);
430 }
431
432 /**
433  * Return payload of msecs attribute
434  * @arg nla             msecs netlink attribute
435  *
436  * @return the number of milliseconds.
437  */
438 static inline unsigned long nla_get_msecs(struct nlattr *nla)
439 {
440         return nla_get_u64(nla);
441 }
442
443 /**
444  * Add nested attributes to netlink message.
445  * @arg msg             Netlink message.
446  * @arg attrtype        Attribute type.
447  * @arg nested          Message containing attributes to be nested.
448  *
449  * Takes the attributes found in the \a nested message and appends them
450  * to the message \a msg nested in a container of the type \a attrtype.
451  * The \a nested message may not have a family specific header.
452  *
453  * @see nla_put
454  * @return 0 on success or a negative error code.
455  */
456 static inline int nla_put_nested(struct nl_msg *msg, int attrtype, struct nl_msg *nested)
457 {
458         return nla_put(msg, attrtype, nlmsg_len(nested->nm_nlh),
459                        nlmsg_data(nested->nm_nlh));
460 }
461
462 /**
463  * Start a new level of nested attributes.
464  * @arg msg             Netlink message.
465  * @arg attrtype        Attribute type of container.
466  *
467  * @return Pointer to container attribute.
468  */
469 static inline struct nlattr *nla_nest_start(struct nl_msg *msg, int attrtype)
470 {
471         struct nlattr *start = (struct nlattr *) nlmsg_tail(msg->nm_nlh);
472
473         if (nla_put(msg, attrtype, 0, NULL) < 0)
474                 return NULL;
475
476         return start;
477 }
478
479 /**
480  * Finalize nesting of attributes.
481  * @arg msg             Netlink message.
482  * @arg start           Container attribute as returned from nla_nest_start().
483  *
484  * Corrects the container attribute header to include the appeneded attributes.
485  *
486  * @return 0
487  */
488 static inline int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
489 {
490         start->nla_len = (unsigned char *) nlmsg_tail(msg->nm_nlh) -
491                                 (unsigned char *) start;
492         return 0;
493 }
494
495 /**
496  * Create attribute index based on nested attribute
497  * @arg tb              Index array to be filled (maxtype+1 elements).
498  * @arg maxtype         Maximum attribute type expected and accepted.
499  * @arg nla             Nested Attribute.
500  * @arg policy          Attribute validation policy.
501  *
502  * Feeds the stream of attributes nested into the specified attribute
503  * to nla_parse().
504  *
505  * @see nla_parse
506  * @return 0 on success or a negative error code.
507  */
508 static inline int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla,
509                      struct nla_policy *policy)
510 {
511         return nla_parse(tb, maxtype, (struct nlattr *)nla_data(nla), nla_len(nla), policy);
512 }
513
514 /**
515  * Compare attribute payload with memory area.
516  * @arg nla             Attribute.
517  * @arg data            Memory area to compare to.
518  * @arg size            Number of bytes to compare.
519  *
520  * @see memcmp(3)
521  * @return An integer less than, equal to, or greater than zero.
522  */
523 static inline int nla_memcmp(const struct nlattr *nla, const void *data, size_t size)
524 {
525         int d = nla_len(nla) - size;
526
527         if (d == 0)
528                 d = memcmp(nla_data(nla), data, size);
529
530         return d;
531 }
532
533 /**
534  * Compare string attribute payload with string
535  * @arg nla             Attribute of type NLA_STRING.
536  * @arg str             NUL terminated string.
537  *
538  * @see strcmp(3)
539  * @return An integer less than, equal to, or greater than zero.
540  */
541 static inline int nla_strcmp(const struct nlattr *nla, const char *str)
542 {
543         int len = strlen(str) + 1;
544         int d = nla_len(nla) - len;
545
546         if (d == 0)
547                 d = memcmp(nla_data(nla), str, len);
548
549         return d;
550 }
551
552 /**
553  * Copy string attribute payload to a buffer.
554  * @arg dst             Pointer to destination buffer.
555  * @arg nla             Attribute of type NLA_STRING.
556  * @arg dstsize         Size of destination buffer in bytes.
557  *
558  * Copies at most dstsize - 1 bytes to the destination buffer.
559  * The result is always a valid NUL terminated string. Unlike
560  * strlcpy the destination buffer is always padded out.
561  *
562  * @return The length of string attribute without the terminating NUL.
563  */
564 static inline size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
565 {
566         size_t srclen = (size_t)nla_len(nla);
567         char *src = (char*)nla_data(nla);
568
569         if (srclen > 0 && src[srclen - 1] == '\0')
570                 srclen--;
571
572         if (dstsize > 0) {
573                 size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
574
575                 memset(dst, 0, dstsize);
576                 memcpy(dst, src, len);
577         }
578
579         return srclen;
580 }
581
582
583 /**
584  * @name Attribute Construction (Exception Based)
585  * @{
586  */
587
588 /**
589  * @ingroup attr
590  * Add unspecific attribute to netlink message.
591  * @arg msg             Netlink message.
592  * @arg attrtype        Attribute type.
593  * @arg attrlen         Length of attribute payload.
594  * @arg data            Head of attribute payload.
595  */
596 #define NLA_PUT(msg, attrtype, attrlen, data) \
597         do { \
598                 if (nla_put(msg, attrtype, attrlen, data) < 0) \
599                         goto nla_put_failure; \
600         } while(0)
601
602 /**
603  * @ingroup attr
604  * Add atomic type attribute to netlink message.
605  * @arg msg             Netlink message.
606  * @arg type            Atomic type.
607  * @arg attrtype        Attribute type.
608  * @arg value           Head of attribute payload.
609  */
610 #define NLA_PUT_TYPE(msg, type, attrtype, value) \
611         do { \
612                 type __tmp = value; \
613                 NLA_PUT(msg, attrtype, sizeof(type), &__tmp); \
614         } while(0)
615
616 /**
617  * Add 8 bit integer attribute to netlink message.
618  * @arg msg             Netlink message.
619  * @arg attrtype        Attribute type.
620  * @arg value           Numeric value.
621  */
622 #define NLA_PUT_U8(msg, attrtype, value) \
623         NLA_PUT_TYPE(msg, uint8_t, attrtype, value)
624
625 /**
626  * Add 16 bit integer attribute to netlink message.
627  * @arg msg             Netlink message.
628  * @arg attrtype        Attribute type.
629  * @arg value           Numeric value.
630  */
631 #define NLA_PUT_U16(msg, attrtype, value) \
632         NLA_PUT_TYPE(msg, uint16_t, attrtype, value)
633
634 /**
635  * Add 32 bit integer attribute to netlink message.
636  * @arg msg             Netlink message.
637  * @arg attrtype        Attribute type.
638  * @arg value           Numeric value.
639  */
640 #define NLA_PUT_U32(msg, attrtype, value) \
641         NLA_PUT_TYPE(msg, uint32_t, attrtype, value)
642
643 /**
644  * Add 64 bit integer attribute to netlink message.
645  * @arg msg             Netlink message.
646  * @arg attrtype        Attribute type.
647  * @arg value           Numeric value.
648  */
649 #define NLA_PUT_U64(msg, attrtype, value) \
650         NLA_PUT_TYPE(msg, uint64_t, attrtype, value)
651
652 /**
653  * Add string attribute to netlink message.
654  * @arg msg             Netlink message.
655  * @arg attrtype        Attribute type.
656  * @arg value           NUL terminated character string.
657  */
658 #define NLA_PUT_STRING(msg, attrtype, value) \
659         NLA_PUT(msg, attrtype, strlen(value) + 1, value)
660
661 /**
662  * Add flag attribute to netlink message.
663  * @arg msg             Netlink message.
664  * @arg attrtype        Attribute type.
665  */
666 #define NLA_PUT_FLAG(msg, attrtype) \
667         NLA_PUT(msg, attrtype, 0, NULL)
668
669 /**
670  * Add msecs attribute to netlink message.
671  * @arg msg             Netlink message.
672  * @arg attrtype        Attribute type.
673  * @arg msecs           Numeric value in micro seconds.
674  */
675 #define NLA_PUT_MSECS(msg, attrtype, msecs) \
676         NLA_PUT_U64(msg, attrtype, msecs)
677
678 /**
679  * Add address attribute to netlink message.
680  * @arg msg             Netlink message.
681  * @arg attrtype        Attribute type.
682  * @arg addr            Abstract address object.
683  */
684 #define NLA_PUT_ADDR(msg, attrtype, addr) \
685         NLA_PUT(msg, attrtype, nl_addr_get_len(addr), \
686                 nl_addr_get_binary_addr(addr))
687
688 /** @} */
689
690 /**
691  * @name Iterators
692  * @{
693  */
694
695 /**
696  * @ingroup attr
697  * Iterate over a stream of attributes
698  * @arg pos     loop counter, set to current attribute
699  * @arg head    head of attribute stream
700  * @arg len     length of attribute stream
701  * @arg rem     initialized to len, holds bytes currently remaining in stream
702  */
703 #define nla_for_each_attr(pos, head, len, rem) \
704         for (pos = head, rem = len; \
705              nla_ok(pos, rem); \
706              pos = nla_next(pos, &(rem)))
707
708 /**
709  * @ingroup attr
710  * Iterate over a stream of nested attributes
711  * @arg pos     loop counter, set to current attribute
712  * @arg nla     attribute containing the nested attributes
713  * @arg rem     initialized to len, holds bytes currently remaining in stream
714  */
715 #define nla_for_each_nested(pos, nla, rem) \
716         for (pos = (struct nlattr *)nla_data(nla), rem = nla_len(nla); \
717              nla_ok(pos, rem); \
718              pos = nla_next(pos, &(rem)))
719
720 /** @} */
721
722 #ifdef __cplusplus
723 }
724 #endif
725
726 #endif