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