Home | History | Annotate | Download | only in netlink
      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-2013 Thomas Graf <tgraf (at) 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 
     20 #ifdef __cplusplus
     21 extern "C" {
     22 #endif
     23 
     24 struct nl_msg;
     25 
     26 /**
     27  * @name Basic Attribute Data Types
     28  * @{
     29  */
     30 
     31 /**
     32  * @ingroup attr
     33  * Basic attribute data types
     34  *
     35  * See section @core_doc{core_attr_parse,Attribute Parsing} for more details.
     36  */
     37 enum {
     38 	NLA_UNSPEC,	/**< Unspecified type, binary data chunk */
     39 	NLA_U8,		/**< 8 bit integer */
     40 	NLA_U16,	/**< 16 bit integer */
     41 	NLA_U32,	/**< 32 bit integer */
     42 	NLA_U64,	/**< 64 bit integer */
     43 	NLA_STRING,	/**< NUL terminated character string */
     44 	NLA_FLAG,	/**< Flag */
     45 	NLA_MSECS,	/**< Micro seconds (64bit) */
     46 	NLA_NESTED,	/**< Nested attributes */
     47 	__NLA_TYPE_MAX,
     48 };
     49 
     50 #define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1)
     51 
     52 /** @} */
     53 
     54 /**
     55  * @ingroup attr
     56  * Attribute validation policy.
     57  *
     58  * See section @core_doc{core_attr_parse,Attribute Parsing} for more details.
     59  */
     60 struct nla_policy {
     61 	/** Type of attribute or NLA_UNSPEC */
     62 	uint16_t	type;
     63 
     64 	/** Minimal length of payload required */
     65 	uint16_t	minlen;
     66 
     67 	/** Maximal length of payload allowed */
     68 	uint16_t	maxlen;
     69 };
     70 
     71 /* Size calculations */
     72 extern int		nla_attr_size(int payload);
     73 extern int		nla_total_size(int payload);
     74 extern int		nla_padlen(int payload);
     75 
     76 /* Attribute parsing */
     77 extern int		nla_type(const struct nlattr *);
     78 extern void *		nla_data(const struct nlattr *);
     79 extern int		nla_len(const struct nlattr *);
     80 extern int		nla_ok(const struct nlattr *, int);
     81 extern struct nlattr *	nla_next(const struct nlattr *, int *);
     82 extern int		nla_parse(struct nlattr **, int, struct nlattr *,
     83 				  int, struct nla_policy *);
     84 extern int		nla_validate(struct nlattr *, int, int,
     85 				     struct nla_policy *);
     86 extern struct nlattr *	nla_find(struct nlattr *, int, int);
     87 
     88 /* Helper Functions */
     89 extern int		nla_memcpy(void *, struct nlattr *, int);
     90 extern size_t		nla_strlcpy(char *, const struct nlattr *, size_t);
     91 extern int		nla_memcmp(const struct nlattr *, const void *, size_t);
     92 extern int		nla_strcmp(const struct nlattr *, const char *);
     93 
     94 /* Unspecific attribute */
     95 extern struct nlattr *	nla_reserve(struct nl_msg *, int, int);
     96 extern int		nla_put(struct nl_msg *, int, int, const void *);
     97 extern int		nla_put_data(struct nl_msg *, int, struct nl_data *);
     98 extern int		nla_put_addr(struct nl_msg *, int, struct nl_addr *);
     99 
    100 /* Integer attribute */
    101 extern uint8_t		nla_get_u8(struct nlattr *);
    102 extern int		nla_put_u8(struct nl_msg *, int, uint8_t);
    103 extern uint16_t		nla_get_u16(struct nlattr *);
    104 extern int		nla_put_u16(struct nl_msg *, int, uint16_t);
    105 extern uint32_t		nla_get_u32(struct nlattr *);
    106 extern int		nla_put_u32(struct nl_msg *, int, uint32_t);
    107 extern uint64_t		nla_get_u64(struct nlattr *);
    108 extern int		nla_put_u64(struct nl_msg *, int, uint64_t);
    109 
    110 /* String attribute */
    111 extern char *		nla_get_string(struct nlattr *);
    112 extern char *		nla_strdup(struct nlattr *);
    113 extern int		nla_put_string(struct nl_msg *, int, const char *);
    114 
    115 /* Flag attribute */
    116 extern int		nla_get_flag(struct nlattr *);
    117 extern int		nla_put_flag(struct nl_msg *, int);
    118 
    119 /* Msec attribute */
    120 extern unsigned long	nla_get_msecs(struct nlattr *);
    121 extern int		nla_put_msecs(struct nl_msg *, int, unsigned long);
    122 
    123 /* Attribute nesting */
    124 extern int		nla_put_nested(struct nl_msg *, int, struct nl_msg *);
    125 extern struct nlattr *	nla_nest_start(struct nl_msg *, int);
    126 extern int		nla_nest_end(struct nl_msg *, struct nlattr *);
    127 extern void		nla_nest_cancel(struct nl_msg *, struct nlattr *);
    128 extern int		nla_parse_nested(struct nlattr **, int, struct nlattr *,
    129 					 struct nla_policy *);
    130 extern int		nla_is_nested(struct nlattr *);
    131 
    132 /**
    133  * @name Attribute Construction (Exception Based)
    134  * @{
    135  */
    136 
    137 /**
    138  * @ingroup attr
    139  * Add unspecific attribute to netlink message.
    140  * @arg msg		Netlink message.
    141  * @arg attrtype	Attribute type.
    142  * @arg attrlen		Length of attribute payload.
    143  * @arg data		Head of attribute payload.
    144  */
    145 #define NLA_PUT(msg, attrtype, attrlen, data) \
    146 	do { \
    147 		if (nla_put(msg, attrtype, attrlen, data) < 0) \
    148 			goto nla_put_failure; \
    149 	} while(0)
    150 
    151 /**
    152  * @ingroup attr
    153  * Add atomic type attribute to netlink message.
    154  * @arg msg		Netlink message.
    155  * @arg type		Atomic type.
    156  * @arg attrtype	Attribute type.
    157  * @arg value		Head of attribute payload.
    158  */
    159 #define NLA_PUT_TYPE(msg, type, attrtype, value) \
    160 	do { \
    161 		type __tmp = value; \
    162 		NLA_PUT(msg, attrtype, sizeof(type), &__tmp); \
    163 	} while(0)
    164 
    165 /**
    166  * Add 8 bit integer attribute to netlink message.
    167  * @arg msg		Netlink message.
    168  * @arg attrtype	Attribute type.
    169  * @arg value		Numeric value.
    170  */
    171 #define NLA_PUT_U8(msg, attrtype, value) \
    172 	NLA_PUT_TYPE(msg, uint8_t, attrtype, value)
    173 
    174 /**
    175  * Add 16 bit integer attribute to netlink message.
    176  * @arg msg		Netlink message.
    177  * @arg attrtype	Attribute type.
    178  * @arg value		Numeric value.
    179  */
    180 #define NLA_PUT_U16(msg, attrtype, value) \
    181 	NLA_PUT_TYPE(msg, uint16_t, attrtype, value)
    182 
    183 /**
    184  * Add 32 bit integer attribute to netlink message.
    185  * @arg msg		Netlink message.
    186  * @arg attrtype	Attribute type.
    187  * @arg value		Numeric value.
    188  */
    189 #define NLA_PUT_U32(msg, attrtype, value) \
    190 	NLA_PUT_TYPE(msg, uint32_t, attrtype, value)
    191 
    192 /**
    193  * Add 64 bit integer attribute to netlink message.
    194  * @arg msg		Netlink message.
    195  * @arg attrtype	Attribute type.
    196  * @arg value		Numeric value.
    197  */
    198 #define NLA_PUT_U64(msg, attrtype, value) \
    199 	NLA_PUT_TYPE(msg, uint64_t, attrtype, value)
    200 
    201 /**
    202  * Add string attribute to netlink message.
    203  * @arg msg		Netlink message.
    204  * @arg attrtype	Attribute type.
    205  * @arg value		NUL terminated character string.
    206  */
    207 #define NLA_PUT_STRING(msg, attrtype, value) \
    208 	NLA_PUT(msg, attrtype, (int) strlen(value) + 1, value)
    209 
    210 /**
    211  * Add flag attribute to netlink message.
    212  * @arg msg		Netlink message.
    213  * @arg attrtype	Attribute type.
    214  */
    215 #define NLA_PUT_FLAG(msg, attrtype) \
    216 	NLA_PUT(msg, attrtype, 0, NULL)
    217 
    218 /**
    219  * Add msecs attribute to netlink message.
    220  * @arg msg		Netlink message.
    221  * @arg attrtype	Attribute type.
    222  * @arg msecs		Numeric value in micro seconds.
    223  */
    224 #define NLA_PUT_MSECS(msg, attrtype, msecs) \
    225 	NLA_PUT_U64(msg, attrtype, msecs)
    226 
    227 /**
    228  * Add address attribute to netlink message.
    229  * @arg msg		Netlink message.
    230  * @arg attrtype	Attribute type.
    231  * @arg addr		Abstract address object.
    232  */
    233 #define NLA_PUT_ADDR(msg, attrtype, addr) \
    234 	NLA_PUT(msg, attrtype, nl_addr_get_len(addr), \
    235 		nl_addr_get_binary_addr(addr))
    236 
    237 /**
    238  * Add abstract data attribute to netlink message.
    239  * @arg msg		Netlink message.
    240  * @arg attrtype	Attribute type.
    241  * @arg data		Abstract data object.
    242  */
    243 #define NLA_PUT_DATA(msg, attrtype, data) \
    244 	NLA_PUT(msg, attrtype, nl_data_get_size(data), \
    245 		nl_data_get(data))
    246 
    247 /** @} */
    248 
    249 /**
    250  * @name Iterators
    251  * @{
    252  */
    253 
    254 /**
    255  * @ingroup attr
    256  * Iterate over a stream of attributes
    257  * @arg pos	loop counter, set to current attribute
    258  * @arg head	head of attribute stream
    259  * @arg len	length of attribute stream
    260  * @arg rem	initialized to len, holds bytes currently remaining in stream
    261  */
    262 #define nla_for_each_attr(pos, head, len, rem) \
    263 	for (pos = head, rem = len; \
    264 	     nla_ok(pos, rem); \
    265 	     pos = nla_next(pos, &(rem)))
    266 
    267 /**
    268  * @ingroup attr
    269  * Iterate over a stream of nested attributes
    270  * @arg pos	loop counter, set to current attribute
    271  * @arg nla	attribute containing the nested attributes
    272  * @arg rem	initialized to len, holds bytes currently remaining in stream
    273  */
    274 #define nla_for_each_nested(pos, nla, rem) \
    275 	for (pos = nla_data(nla), rem = nla_len(nla); \
    276 	     nla_ok(pos, rem); \
    277 	     pos = nla_next(pos, &(rem)))
    278 
    279 /** @} */
    280 
    281 #ifdef __cplusplus
    282 }
    283 #endif
    284 
    285 #endif
    286