xref: /openbmc/linux/include/net/netlink.h (revision cd40b7d3)
1bfa83a9eSThomas Graf #ifndef __NET_NETLINK_H
2bfa83a9eSThomas Graf #define __NET_NETLINK_H
3bfa83a9eSThomas Graf 
4bfa83a9eSThomas Graf #include <linux/types.h>
5bfa83a9eSThomas Graf #include <linux/netlink.h>
6d7fe0f24SAl Viro #include <linux/jiffies.h>
7bfa83a9eSThomas Graf 
8bfa83a9eSThomas Graf /* ========================================================================
9bfa83a9eSThomas Graf  *         Netlink Messages and Attributes Interface (As Seen On TV)
10bfa83a9eSThomas Graf  * ------------------------------------------------------------------------
11bfa83a9eSThomas Graf  *                          Messages Interface
12bfa83a9eSThomas Graf  * ------------------------------------------------------------------------
13bfa83a9eSThomas Graf  *
14bfa83a9eSThomas Graf  * Message Format:
15bfa83a9eSThomas Graf  *    <--- nlmsg_total_size(payload)  --->
16bfa83a9eSThomas Graf  *    <-- nlmsg_msg_size(payload) ->
17bfa83a9eSThomas Graf  *   +----------+- - -+-------------+- - -+-------- - -
18bfa83a9eSThomas Graf  *   | nlmsghdr | Pad |   Payload   | Pad | nlmsghdr
19bfa83a9eSThomas Graf  *   +----------+- - -+-------------+- - -+-------- - -
20bfa83a9eSThomas Graf  *   nlmsg_data(nlh)---^                   ^
21bfa83a9eSThomas Graf  *   nlmsg_next(nlh)-----------------------+
22bfa83a9eSThomas Graf  *
23bfa83a9eSThomas Graf  * Payload Format:
24bfa83a9eSThomas Graf  *    <---------------------- nlmsg_len(nlh) --------------------->
25bfa83a9eSThomas Graf  *    <------ hdrlen ------>       <- nlmsg_attrlen(nlh, hdrlen) ->
26bfa83a9eSThomas Graf  *   +----------------------+- - -+--------------------------------+
27bfa83a9eSThomas Graf  *   |     Family Header    | Pad |           Attributes           |
28bfa83a9eSThomas Graf  *   +----------------------+- - -+--------------------------------+
29bfa83a9eSThomas Graf  *   nlmsg_attrdata(nlh, hdrlen)---^
30bfa83a9eSThomas Graf  *
31bfa83a9eSThomas Graf  * Data Structures:
32bfa83a9eSThomas Graf  *   struct nlmsghdr			netlink message header
33bfa83a9eSThomas Graf  *
34bfa83a9eSThomas Graf  * Message Construction:
35bfa83a9eSThomas Graf  *   nlmsg_new()			create a new netlink message
36bfa83a9eSThomas Graf  *   nlmsg_put()			add a netlink message to an skb
37bfa83a9eSThomas Graf  *   nlmsg_put_answer()			callback based nlmsg_put()
38bfa83a9eSThomas Graf  *   nlmsg_end()			finanlize netlink message
39fe4944e5SThomas Graf  *   nlmsg_get_pos()			return current position in message
40fe4944e5SThomas Graf  *   nlmsg_trim()			trim part of message
41bfa83a9eSThomas Graf  *   nlmsg_cancel()			cancel message construction
42bfa83a9eSThomas Graf  *   nlmsg_free()			free a netlink message
43bfa83a9eSThomas Graf  *
44bfa83a9eSThomas Graf  * Message Sending:
45bfa83a9eSThomas Graf  *   nlmsg_multicast()			multicast message to several groups
46bfa83a9eSThomas Graf  *   nlmsg_unicast()			unicast a message to a single socket
47d387f6adSThomas Graf  *   nlmsg_notify()			send notification message
48bfa83a9eSThomas Graf  *
49bfa83a9eSThomas Graf  * Message Length Calculations:
50bfa83a9eSThomas Graf  *   nlmsg_msg_size(payload)		length of message w/o padding
51bfa83a9eSThomas Graf  *   nlmsg_total_size(payload)		length of message w/ padding
52bfa83a9eSThomas Graf  *   nlmsg_padlen(payload)		length of padding at tail
53bfa83a9eSThomas Graf  *
54bfa83a9eSThomas Graf  * Message Payload Access:
55bfa83a9eSThomas Graf  *   nlmsg_data(nlh)			head of message payload
56bfa83a9eSThomas Graf  *   nlmsg_len(nlh)			length of message payload
57bfa83a9eSThomas Graf  *   nlmsg_attrdata(nlh, hdrlen)	head of attributes data
58bfa83a9eSThomas Graf  *   nlmsg_attrlen(nlh, hdrlen)		length of attributes data
59bfa83a9eSThomas Graf  *
60bfa83a9eSThomas Graf  * Message Parsing:
61bfa83a9eSThomas Graf  *   nlmsg_ok(nlh, remaining)		does nlh fit into remaining bytes?
62bfa83a9eSThomas Graf  *   nlmsg_next(nlh, remaining)		get next netlink message
63bfa83a9eSThomas Graf  *   nlmsg_parse()			parse attributes of a message
64bfa83a9eSThomas Graf  *   nlmsg_find_attr()			find an attribute in a message
65bfa83a9eSThomas Graf  *   nlmsg_for_each_msg()		loop over all messages
66bfa83a9eSThomas Graf  *   nlmsg_validate()			validate netlink message incl. attrs
67bfa83a9eSThomas Graf  *   nlmsg_for_each_attr()		loop over all attributes
68bfa83a9eSThomas Graf  *
6997676b6bSThomas Graf  * Misc:
7097676b6bSThomas Graf  *   nlmsg_report()			report back to application?
7197676b6bSThomas Graf  *
72bfa83a9eSThomas Graf  * ------------------------------------------------------------------------
73bfa83a9eSThomas Graf  *                          Attributes Interface
74bfa83a9eSThomas Graf  * ------------------------------------------------------------------------
75bfa83a9eSThomas Graf  *
76bfa83a9eSThomas Graf  * Attribute Format:
77bfa83a9eSThomas Graf  *    <------- nla_total_size(payload) ------->
78bfa83a9eSThomas Graf  *    <---- nla_attr_size(payload) ----->
79bfa83a9eSThomas Graf  *   +----------+- - -+- - - - - - - - - +- - -+-------- - -
80bfa83a9eSThomas Graf  *   |  Header  | Pad |     Payload      | Pad |  Header
81bfa83a9eSThomas Graf  *   +----------+- - -+- - - - - - - - - +- - -+-------- - -
82bfa83a9eSThomas Graf  *                     <- nla_len(nla) ->      ^
83bfa83a9eSThomas Graf  *   nla_data(nla)----^                        |
84bfa83a9eSThomas Graf  *   nla_next(nla)-----------------------------'
85bfa83a9eSThomas Graf  *
86bfa83a9eSThomas Graf  * Data Structures:
87d1ec3b77SPierre Ynard  *   struct nlattr			netlink attribute header
88bfa83a9eSThomas Graf  *
89bfa83a9eSThomas Graf  * Attribute Construction:
90fe4944e5SThomas Graf  *   nla_reserve(skb, type, len)	reserve room for an attribute
91fe4944e5SThomas Graf  *   nla_reserve_nohdr(skb, len)	reserve room for an attribute w/o hdr
92bfa83a9eSThomas Graf  *   nla_put(skb, type, len, data)	add attribute to skb
93fe4944e5SThomas Graf  *   nla_put_nohdr(skb, len, data)	add attribute w/o hdr
94bfa83a9eSThomas Graf  *
95bfa83a9eSThomas Graf  * Attribute Construction for Basic Types:
96bfa83a9eSThomas Graf  *   nla_put_u8(skb, type, value)	add u8 attribute to skb
97bfa83a9eSThomas Graf  *   nla_put_u16(skb, type, value)	add u16 attribute to skb
98bfa83a9eSThomas Graf  *   nla_put_u32(skb, type, value)	add u32 attribute to skb
99bfa83a9eSThomas Graf  *   nla_put_u64(skb, type, value)	add u64 attribute to skb
100bfa83a9eSThomas Graf  *   nla_put_string(skb, type, str)	add string attribute to skb
101bfa83a9eSThomas Graf  *   nla_put_flag(skb, type)		add flag attribute to skb
102bfa83a9eSThomas Graf  *   nla_put_msecs(skb, type, jiffies)	add msecs attribute to skb
103bfa83a9eSThomas Graf  *
104bfa83a9eSThomas Graf  * Exceptions Based Attribute Construction:
105bfa83a9eSThomas Graf  *   NLA_PUT(skb, type, len, data)	add attribute to skb
106bfa83a9eSThomas Graf  *   NLA_PUT_U8(skb, type, value)	add u8 attribute to skb
107bfa83a9eSThomas Graf  *   NLA_PUT_U16(skb, type, value)	add u16 attribute to skb
108bfa83a9eSThomas Graf  *   NLA_PUT_U32(skb, type, value)	add u32 attribute to skb
109bfa83a9eSThomas Graf  *   NLA_PUT_U64(skb, type, value)	add u64 attribute to skb
110bfa83a9eSThomas Graf  *   NLA_PUT_STRING(skb, type, str)	add string attribute to skb
111bfa83a9eSThomas Graf  *   NLA_PUT_FLAG(skb, type)		add flag attribute to skb
112bfa83a9eSThomas Graf  *   NLA_PUT_MSECS(skb, type, jiffies)	add msecs attribute to skb
113bfa83a9eSThomas Graf  *
114bfa83a9eSThomas Graf  *   The meaning of these functions is equal to their lower case
115bfa83a9eSThomas Graf  *   variants but they jump to the label nla_put_failure in case
116bfa83a9eSThomas Graf  *   of a failure.
117bfa83a9eSThomas Graf  *
118bfa83a9eSThomas Graf  * Nested Attributes Construction:
119bfa83a9eSThomas Graf  *   nla_nest_start(skb, type)		start a nested attribute
120bfa83a9eSThomas Graf  *   nla_nest_end(skb, nla)		finalize a nested attribute
1211092cb21SPatrick McHardy  *   nla_nest_compat_start(skb, type,	start a nested compat attribute
1221092cb21SPatrick McHardy  *			   len, data)
1231092cb21SPatrick McHardy  *   nla_nest_compat_end(skb, type)	finalize a nested compat attribute
124bfa83a9eSThomas Graf  *   nla_nest_cancel(skb, nla)		cancel nested attribute construction
125bfa83a9eSThomas Graf  *
126bfa83a9eSThomas Graf  * Attribute Length Calculations:
127bfa83a9eSThomas Graf  *   nla_attr_size(payload)		length of attribute w/o padding
128bfa83a9eSThomas Graf  *   nla_total_size(payload)		length of attribute w/ padding
129bfa83a9eSThomas Graf  *   nla_padlen(payload)		length of padding
130bfa83a9eSThomas Graf  *
131bfa83a9eSThomas Graf  * Attribute Payload Access:
132bfa83a9eSThomas Graf  *   nla_data(nla)			head of attribute payload
133bfa83a9eSThomas Graf  *   nla_len(nla)			length of attribute payload
134bfa83a9eSThomas Graf  *
135bfa83a9eSThomas Graf  * Attribute Payload Access for Basic Types:
136bfa83a9eSThomas Graf  *   nla_get_u8(nla)			get payload for a u8 attribute
137bfa83a9eSThomas Graf  *   nla_get_u16(nla)			get payload for a u16 attribute
138bfa83a9eSThomas Graf  *   nla_get_u32(nla)			get payload for a u32 attribute
139bfa83a9eSThomas Graf  *   nla_get_u64(nla)			get payload for a u64 attribute
140bfa83a9eSThomas Graf  *   nla_get_flag(nla)			return 1 if flag is true
141bfa83a9eSThomas Graf  *   nla_get_msecs(nla)			get payload for a msecs attribute
142bfa83a9eSThomas Graf  *
143bfa83a9eSThomas Graf  * Attribute Misc:
144bfa83a9eSThomas Graf  *   nla_memcpy(dest, nla, count)	copy attribute into memory
145bfa83a9eSThomas Graf  *   nla_memcmp(nla, data, size)	compare attribute with memory area
146bfa83a9eSThomas Graf  *   nla_strlcpy(dst, nla, size)	copy attribute to a sized string
147bfa83a9eSThomas Graf  *   nla_strcmp(nla, str)		compare attribute with string
148bfa83a9eSThomas Graf  *
149bfa83a9eSThomas Graf  * Attribute Parsing:
150bfa83a9eSThomas Graf  *   nla_ok(nla, remaining)		does nla fit into remaining bytes?
151bfa83a9eSThomas Graf  *   nla_next(nla, remaining)		get next netlink attribute
152bfa83a9eSThomas Graf  *   nla_validate()			validate a stream of attributes
1534fe5d5c0SPaul Moore  *   nla_validate_nested()		validate a stream of nested attributes
154bfa83a9eSThomas Graf  *   nla_find()				find attribute in stream of attributes
155fe4944e5SThomas Graf  *   nla_find_nested()			find attribute in nested attributes
156bfa83a9eSThomas Graf  *   nla_parse()			parse and validate stream of attrs
157bfa83a9eSThomas Graf  *   nla_parse_nested()			parse nested attribuets
1581092cb21SPatrick McHardy  *   nla_parse_nested_compat()		parse nested compat attributes
159bfa83a9eSThomas Graf  *   nla_for_each_attr()		loop over all attributes
16022acb19aSPaul Moore  *   nla_for_each_nested()		loop over the nested attributes
161bfa83a9eSThomas Graf  *=========================================================================
162bfa83a9eSThomas Graf  */
163bfa83a9eSThomas Graf 
164bfa83a9eSThomas Graf  /**
165bfa83a9eSThomas Graf   * Standard attribute types to specify validation policy
166bfa83a9eSThomas Graf   */
167bfa83a9eSThomas Graf enum {
168bfa83a9eSThomas Graf 	NLA_UNSPEC,
169bfa83a9eSThomas Graf 	NLA_U8,
170bfa83a9eSThomas Graf 	NLA_U16,
171bfa83a9eSThomas Graf 	NLA_U32,
172bfa83a9eSThomas Graf 	NLA_U64,
173bfa83a9eSThomas Graf 	NLA_STRING,
174bfa83a9eSThomas Graf 	NLA_FLAG,
175bfa83a9eSThomas Graf 	NLA_MSECS,
176bfa83a9eSThomas Graf 	NLA_NESTED,
1771092cb21SPatrick McHardy 	NLA_NESTED_COMPAT,
178a5531a5dSThomas Graf 	NLA_NUL_STRING,
179d30045a0SJohannes Berg 	NLA_BINARY,
180bfa83a9eSThomas Graf 	__NLA_TYPE_MAX,
181bfa83a9eSThomas Graf };
182bfa83a9eSThomas Graf 
183bfa83a9eSThomas Graf #define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1)
184bfa83a9eSThomas Graf 
185bfa83a9eSThomas Graf /**
186bfa83a9eSThomas Graf  * struct nla_policy - attribute validation policy
187bfa83a9eSThomas Graf  * @type: Type of attribute or NLA_UNSPEC
188a5531a5dSThomas Graf  * @len: Type specific length of payload
189bfa83a9eSThomas Graf  *
190bfa83a9eSThomas Graf  * Policies are defined as arrays of this struct, the array must be
191bfa83a9eSThomas Graf  * accessible by attribute type up to the highest identifier to be expected.
192bfa83a9eSThomas Graf  *
193a5531a5dSThomas Graf  * Meaning of `len' field:
194a5531a5dSThomas Graf  *    NLA_STRING           Maximum length of string
195a5531a5dSThomas Graf  *    NLA_NUL_STRING       Maximum length of string (excluding NUL)
196a5531a5dSThomas Graf  *    NLA_FLAG             Unused
197d30045a0SJohannes Berg  *    NLA_BINARY           Maximum length of attribute payload
1981092cb21SPatrick McHardy  *    NLA_NESTED_COMPAT    Exact length of structure payload
199a5531a5dSThomas Graf  *    All other            Exact length of attribute payload
200a5531a5dSThomas Graf  *
201bfa83a9eSThomas Graf  * Example:
202bfa83a9eSThomas Graf  * static struct nla_policy my_policy[ATTR_MAX+1] __read_mostly = {
203bfa83a9eSThomas Graf  * 	[ATTR_FOO] = { .type = NLA_U16 },
204d30045a0SJohannes Berg  *	[ATTR_BAR] = { .type = NLA_STRING, .len = BARSIZ },
205a5531a5dSThomas Graf  *	[ATTR_BAZ] = { .len = sizeof(struct mystruct) },
206bfa83a9eSThomas Graf  * };
207bfa83a9eSThomas Graf  */
208bfa83a9eSThomas Graf struct nla_policy {
209bfa83a9eSThomas Graf 	u16		type;
210a5531a5dSThomas Graf 	u16		len;
211bfa83a9eSThomas Graf };
212bfa83a9eSThomas Graf 
2134e902c57SThomas Graf /**
2144e902c57SThomas Graf  * struct nl_info - netlink source information
2154e902c57SThomas Graf  * @nlh: Netlink message header of original request
2164e902c57SThomas Graf  * @pid: Netlink PID of requesting application
2174e902c57SThomas Graf  */
2184e902c57SThomas Graf struct nl_info {
2194e902c57SThomas Graf 	struct nlmsghdr		*nlh;
2204e902c57SThomas Graf 	u32			pid;
2214e902c57SThomas Graf };
2224e902c57SThomas Graf 
223cd40b7d3SDenis V. Lunev extern int		netlink_rcv_skb(struct sk_buff *skb,
22482ace47aSThomas Graf 					int (*cb)(struct sk_buff *,
2251d00a4ebSThomas Graf 						  struct nlmsghdr *));
22697676b6bSThomas Graf extern int		nlmsg_notify(struct sock *sk, struct sk_buff *skb,
22797676b6bSThomas Graf 				     u32 pid, unsigned int group, int report,
22897676b6bSThomas Graf 				     gfp_t flags);
22982ace47aSThomas Graf 
230bfa83a9eSThomas Graf extern int		nla_validate(struct nlattr *head, int len, int maxtype,
231ef7c79edSPatrick McHardy 				     const struct nla_policy *policy);
232bfa83a9eSThomas Graf extern int		nla_parse(struct nlattr *tb[], int maxtype,
233bfa83a9eSThomas Graf 				  struct nlattr *head, int len,
234ef7c79edSPatrick McHardy 				  const struct nla_policy *policy);
235bfa83a9eSThomas Graf extern struct nlattr *	nla_find(struct nlattr *head, int len, int attrtype);
236bfa83a9eSThomas Graf extern size_t		nla_strlcpy(char *dst, const struct nlattr *nla,
237bfa83a9eSThomas Graf 				    size_t dstsize);
238bfa83a9eSThomas Graf extern int		nla_memcpy(void *dest, struct nlattr *src, int count);
239bfa83a9eSThomas Graf extern int		nla_memcmp(const struct nlattr *nla, const void *data,
240bfa83a9eSThomas Graf 				   size_t size);
241bfa83a9eSThomas Graf extern int		nla_strcmp(const struct nlattr *nla, const char *str);
242bfa83a9eSThomas Graf extern struct nlattr *	__nla_reserve(struct sk_buff *skb, int attrtype,
243bfa83a9eSThomas Graf 				      int attrlen);
244fe4944e5SThomas Graf extern void *		__nla_reserve_nohdr(struct sk_buff *skb, int attrlen);
245bfa83a9eSThomas Graf extern struct nlattr *	nla_reserve(struct sk_buff *skb, int attrtype,
246bfa83a9eSThomas Graf 				    int attrlen);
247fe4944e5SThomas Graf extern void *		nla_reserve_nohdr(struct sk_buff *skb, int attrlen);
248bfa83a9eSThomas Graf extern void		__nla_put(struct sk_buff *skb, int attrtype,
249bfa83a9eSThomas Graf 				  int attrlen, const void *data);
250fe4944e5SThomas Graf extern void		__nla_put_nohdr(struct sk_buff *skb, int attrlen,
251fe4944e5SThomas Graf 					const void *data);
252bfa83a9eSThomas Graf extern int		nla_put(struct sk_buff *skb, int attrtype,
253bfa83a9eSThomas Graf 				int attrlen, const void *data);
254fe4944e5SThomas Graf extern int		nla_put_nohdr(struct sk_buff *skb, int attrlen,
255fe4944e5SThomas Graf 				      const void *data);
256bfa83a9eSThomas Graf 
257bfa83a9eSThomas Graf /**************************************************************************
258bfa83a9eSThomas Graf  * Netlink Messages
259bfa83a9eSThomas Graf  **************************************************************************/
260bfa83a9eSThomas Graf 
261bfa83a9eSThomas Graf /**
262bfa83a9eSThomas Graf  * nlmsg_msg_size - length of netlink message not including padding
263bfa83a9eSThomas Graf  * @payload: length of message payload
264bfa83a9eSThomas Graf  */
265bfa83a9eSThomas Graf static inline int nlmsg_msg_size(int payload)
266bfa83a9eSThomas Graf {
267bfa83a9eSThomas Graf 	return NLMSG_HDRLEN + payload;
268bfa83a9eSThomas Graf }
269bfa83a9eSThomas Graf 
270bfa83a9eSThomas Graf /**
271bfa83a9eSThomas Graf  * nlmsg_total_size - length of netlink message including padding
272bfa83a9eSThomas Graf  * @payload: length of message payload
273bfa83a9eSThomas Graf  */
274bfa83a9eSThomas Graf static inline int nlmsg_total_size(int payload)
275bfa83a9eSThomas Graf {
276bfa83a9eSThomas Graf 	return NLMSG_ALIGN(nlmsg_msg_size(payload));
277bfa83a9eSThomas Graf }
278bfa83a9eSThomas Graf 
279bfa83a9eSThomas Graf /**
280bfa83a9eSThomas Graf  * nlmsg_padlen - length of padding at the message's tail
281bfa83a9eSThomas Graf  * @payload: length of message payload
282bfa83a9eSThomas Graf  */
283bfa83a9eSThomas Graf static inline int nlmsg_padlen(int payload)
284bfa83a9eSThomas Graf {
285bfa83a9eSThomas Graf 	return nlmsg_total_size(payload) - nlmsg_msg_size(payload);
286bfa83a9eSThomas Graf }
287bfa83a9eSThomas Graf 
288bfa83a9eSThomas Graf /**
289bfa83a9eSThomas Graf  * nlmsg_data - head of message payload
290bfa83a9eSThomas Graf  * @nlh: netlink messsage header
291bfa83a9eSThomas Graf  */
292bfa83a9eSThomas Graf static inline void *nlmsg_data(const struct nlmsghdr *nlh)
293bfa83a9eSThomas Graf {
294bfa83a9eSThomas Graf 	return (unsigned char *) nlh + NLMSG_HDRLEN;
295bfa83a9eSThomas Graf }
296bfa83a9eSThomas Graf 
297bfa83a9eSThomas Graf /**
298bfa83a9eSThomas Graf  * nlmsg_len - length of message payload
299bfa83a9eSThomas Graf  * @nlh: netlink message header
300bfa83a9eSThomas Graf  */
301bfa83a9eSThomas Graf static inline int nlmsg_len(const struct nlmsghdr *nlh)
302bfa83a9eSThomas Graf {
303bfa83a9eSThomas Graf 	return nlh->nlmsg_len - NLMSG_HDRLEN;
304bfa83a9eSThomas Graf }
305bfa83a9eSThomas Graf 
306bfa83a9eSThomas Graf /**
307bfa83a9eSThomas Graf  * nlmsg_attrdata - head of attributes data
308bfa83a9eSThomas Graf  * @nlh: netlink message header
309bfa83a9eSThomas Graf  * @hdrlen: length of family specific header
310bfa83a9eSThomas Graf  */
311bfa83a9eSThomas Graf static inline struct nlattr *nlmsg_attrdata(const struct nlmsghdr *nlh,
312bfa83a9eSThomas Graf 					    int hdrlen)
313bfa83a9eSThomas Graf {
314bfa83a9eSThomas Graf 	unsigned char *data = nlmsg_data(nlh);
315bfa83a9eSThomas Graf 	return (struct nlattr *) (data + NLMSG_ALIGN(hdrlen));
316bfa83a9eSThomas Graf }
317bfa83a9eSThomas Graf 
318bfa83a9eSThomas Graf /**
319bfa83a9eSThomas Graf  * nlmsg_attrlen - length of attributes data
320bfa83a9eSThomas Graf  * @nlh: netlink message header
321bfa83a9eSThomas Graf  * @hdrlen: length of family specific header
322bfa83a9eSThomas Graf  */
323bfa83a9eSThomas Graf static inline int nlmsg_attrlen(const struct nlmsghdr *nlh, int hdrlen)
324bfa83a9eSThomas Graf {
325bfa83a9eSThomas Graf 	return nlmsg_len(nlh) - NLMSG_ALIGN(hdrlen);
326bfa83a9eSThomas Graf }
327bfa83a9eSThomas Graf 
328bfa83a9eSThomas Graf /**
329bfa83a9eSThomas Graf  * nlmsg_ok - check if the netlink message fits into the remaining bytes
330bfa83a9eSThomas Graf  * @nlh: netlink message header
331bfa83a9eSThomas Graf  * @remaining: number of bytes remaining in message stream
332bfa83a9eSThomas Graf  */
333bfa83a9eSThomas Graf static inline int nlmsg_ok(const struct nlmsghdr *nlh, int remaining)
334bfa83a9eSThomas Graf {
335bfa83a9eSThomas Graf 	return (remaining >= sizeof(struct nlmsghdr) &&
336bfa83a9eSThomas Graf 		nlh->nlmsg_len >= sizeof(struct nlmsghdr) &&
337bfa83a9eSThomas Graf 		nlh->nlmsg_len <= remaining);
338bfa83a9eSThomas Graf }
339bfa83a9eSThomas Graf 
340bfa83a9eSThomas Graf /**
341bfa83a9eSThomas Graf  * nlmsg_next - next netlink message in message stream
342bfa83a9eSThomas Graf  * @nlh: netlink message header
343bfa83a9eSThomas Graf  * @remaining: number of bytes remaining in message stream
344bfa83a9eSThomas Graf  *
345bfa83a9eSThomas Graf  * Returns the next netlink message in the message stream and
346bfa83a9eSThomas Graf  * decrements remaining by the size of the current message.
347bfa83a9eSThomas Graf  */
348bfa83a9eSThomas Graf static inline struct nlmsghdr *nlmsg_next(struct nlmsghdr *nlh, int *remaining)
349bfa83a9eSThomas Graf {
350bfa83a9eSThomas Graf 	int totlen = NLMSG_ALIGN(nlh->nlmsg_len);
351bfa83a9eSThomas Graf 
352bfa83a9eSThomas Graf 	*remaining -= totlen;
353bfa83a9eSThomas Graf 
354bfa83a9eSThomas Graf 	return (struct nlmsghdr *) ((unsigned char *) nlh + totlen);
355bfa83a9eSThomas Graf }
356bfa83a9eSThomas Graf 
357bfa83a9eSThomas Graf /**
358bfa83a9eSThomas Graf  * nlmsg_parse - parse attributes of a netlink message
359bfa83a9eSThomas Graf  * @nlh: netlink message header
360bfa83a9eSThomas Graf  * @hdrlen: length of family specific header
361bfa83a9eSThomas Graf  * @tb: destination array with maxtype+1 elements
362bfa83a9eSThomas Graf  * @maxtype: maximum attribute type to be expected
363bfa83a9eSThomas Graf  * @policy: validation policy
364bfa83a9eSThomas Graf  *
365bfa83a9eSThomas Graf  * See nla_parse()
366bfa83a9eSThomas Graf  */
367bfa83a9eSThomas Graf static inline int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen,
368bfa83a9eSThomas Graf 			      struct nlattr *tb[], int maxtype,
369ef7c79edSPatrick McHardy 			      const struct nla_policy *policy)
370bfa83a9eSThomas Graf {
371bfa83a9eSThomas Graf 	if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
372bfa83a9eSThomas Graf 		return -EINVAL;
373bfa83a9eSThomas Graf 
374bfa83a9eSThomas Graf 	return nla_parse(tb, maxtype, nlmsg_attrdata(nlh, hdrlen),
375bfa83a9eSThomas Graf 			 nlmsg_attrlen(nlh, hdrlen), policy);
376bfa83a9eSThomas Graf }
377bfa83a9eSThomas Graf 
378bfa83a9eSThomas Graf /**
379bfa83a9eSThomas Graf  * nlmsg_find_attr - find a specific attribute in a netlink message
380bfa83a9eSThomas Graf  * @nlh: netlink message header
381bfa83a9eSThomas Graf  * @hdrlen: length of familiy specific header
382bfa83a9eSThomas Graf  * @attrtype: type of attribute to look for
383bfa83a9eSThomas Graf  *
384bfa83a9eSThomas Graf  * Returns the first attribute which matches the specified type.
385bfa83a9eSThomas Graf  */
386bfa83a9eSThomas Graf static inline struct nlattr *nlmsg_find_attr(struct nlmsghdr *nlh,
387bfa83a9eSThomas Graf 					     int hdrlen, int attrtype)
388bfa83a9eSThomas Graf {
389bfa83a9eSThomas Graf 	return nla_find(nlmsg_attrdata(nlh, hdrlen),
390bfa83a9eSThomas Graf 			nlmsg_attrlen(nlh, hdrlen), attrtype);
391bfa83a9eSThomas Graf }
392bfa83a9eSThomas Graf 
393bfa83a9eSThomas Graf /**
394bfa83a9eSThomas Graf  * nlmsg_validate - validate a netlink message including attributes
395bfa83a9eSThomas Graf  * @nlh: netlinket message header
396bfa83a9eSThomas Graf  * @hdrlen: length of familiy specific header
397bfa83a9eSThomas Graf  * @maxtype: maximum attribute type to be expected
398bfa83a9eSThomas Graf  * @policy: validation policy
399bfa83a9eSThomas Graf  */
400bfa83a9eSThomas Graf static inline int nlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype,
401ef7c79edSPatrick McHardy 				 const struct nla_policy *policy)
402bfa83a9eSThomas Graf {
403bfa83a9eSThomas Graf 	if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
404bfa83a9eSThomas Graf 		return -EINVAL;
405bfa83a9eSThomas Graf 
406bfa83a9eSThomas Graf 	return nla_validate(nlmsg_attrdata(nlh, hdrlen),
407bfa83a9eSThomas Graf 			    nlmsg_attrlen(nlh, hdrlen), maxtype, policy);
408bfa83a9eSThomas Graf }
409bfa83a9eSThomas Graf 
410bfa83a9eSThomas Graf /**
41197676b6bSThomas Graf  * nlmsg_report - need to report back to application?
41297676b6bSThomas Graf  * @nlh: netlink message header
41397676b6bSThomas Graf  *
41497676b6bSThomas Graf  * Returns 1 if a report back to the application is requested.
41597676b6bSThomas Graf  */
41697676b6bSThomas Graf static inline int nlmsg_report(struct nlmsghdr *nlh)
41797676b6bSThomas Graf {
41897676b6bSThomas Graf 	return !!(nlh->nlmsg_flags & NLM_F_ECHO);
41997676b6bSThomas Graf }
42097676b6bSThomas Graf 
42197676b6bSThomas Graf /**
422bfa83a9eSThomas Graf  * nlmsg_for_each_attr - iterate over a stream of attributes
423bfa83a9eSThomas Graf  * @pos: loop counter, set to current attribute
424bfa83a9eSThomas Graf  * @nlh: netlink message header
425bfa83a9eSThomas Graf  * @hdrlen: length of familiy specific header
426bfa83a9eSThomas Graf  * @rem: initialized to len, holds bytes currently remaining in stream
427bfa83a9eSThomas Graf  */
428bfa83a9eSThomas Graf #define nlmsg_for_each_attr(pos, nlh, hdrlen, rem) \
429bfa83a9eSThomas Graf 	nla_for_each_attr(pos, nlmsg_attrdata(nlh, hdrlen), \
430bfa83a9eSThomas Graf 			  nlmsg_attrlen(nlh, hdrlen), rem)
431bfa83a9eSThomas Graf 
432bfa83a9eSThomas Graf #if 0
433bfa83a9eSThomas Graf /* FIXME: Enable once all users have been converted */
434bfa83a9eSThomas Graf 
435bfa83a9eSThomas Graf /**
436bfa83a9eSThomas Graf  * __nlmsg_put - Add a new netlink message to an skb
437bfa83a9eSThomas Graf  * @skb: socket buffer to store message in
438bfa83a9eSThomas Graf  * @pid: netlink process id
439bfa83a9eSThomas Graf  * @seq: sequence number of message
440bfa83a9eSThomas Graf  * @type: message type
441bfa83a9eSThomas Graf  * @payload: length of message payload
442bfa83a9eSThomas Graf  * @flags: message flags
443bfa83a9eSThomas Graf  *
444bfa83a9eSThomas Graf  * The caller is responsible to ensure that the skb provides enough
445bfa83a9eSThomas Graf  * tailroom for both the netlink header and payload.
446bfa83a9eSThomas Graf  */
447bfa83a9eSThomas Graf static inline struct nlmsghdr *__nlmsg_put(struct sk_buff *skb, u32 pid,
448bfa83a9eSThomas Graf 					   u32 seq, int type, int payload,
449bfa83a9eSThomas Graf 					   int flags)
450bfa83a9eSThomas Graf {
451bfa83a9eSThomas Graf 	struct nlmsghdr *nlh;
452bfa83a9eSThomas Graf 
453bfa83a9eSThomas Graf 	nlh = (struct nlmsghdr *) skb_put(skb, nlmsg_total_size(payload));
454bfa83a9eSThomas Graf 	nlh->nlmsg_type = type;
455bfa83a9eSThomas Graf 	nlh->nlmsg_len = nlmsg_msg_size(payload);
456bfa83a9eSThomas Graf 	nlh->nlmsg_flags = flags;
457bfa83a9eSThomas Graf 	nlh->nlmsg_pid = pid;
458bfa83a9eSThomas Graf 	nlh->nlmsg_seq = seq;
459bfa83a9eSThomas Graf 
460bfa83a9eSThomas Graf 	memset((unsigned char *) nlmsg_data(nlh) + payload, 0,
461bfa83a9eSThomas Graf 	       nlmsg_padlen(payload));
462bfa83a9eSThomas Graf 
463bfa83a9eSThomas Graf 	return nlh;
464bfa83a9eSThomas Graf }
465bfa83a9eSThomas Graf #endif
466bfa83a9eSThomas Graf 
467bfa83a9eSThomas Graf /**
468bfa83a9eSThomas Graf  * nlmsg_put - Add a new netlink message to an skb
469bfa83a9eSThomas Graf  * @skb: socket buffer to store message in
470bfa83a9eSThomas Graf  * @pid: netlink process id
471bfa83a9eSThomas Graf  * @seq: sequence number of message
472bfa83a9eSThomas Graf  * @type: message type
473bfa83a9eSThomas Graf  * @payload: length of message payload
474bfa83a9eSThomas Graf  * @flags: message flags
475bfa83a9eSThomas Graf  *
476bfa83a9eSThomas Graf  * Returns NULL if the tailroom of the skb is insufficient to store
477bfa83a9eSThomas Graf  * the message header and payload.
478bfa83a9eSThomas Graf  */
479bfa83a9eSThomas Graf static inline struct nlmsghdr *nlmsg_put(struct sk_buff *skb, u32 pid, u32 seq,
480bfa83a9eSThomas Graf 					 int type, int payload, int flags)
481bfa83a9eSThomas Graf {
482bfa83a9eSThomas Graf 	if (unlikely(skb_tailroom(skb) < nlmsg_total_size(payload)))
483bfa83a9eSThomas Graf 		return NULL;
484bfa83a9eSThomas Graf 
485bfa83a9eSThomas Graf 	return __nlmsg_put(skb, pid, seq, type, payload, flags);
486bfa83a9eSThomas Graf }
487bfa83a9eSThomas Graf 
488bfa83a9eSThomas Graf /**
489bfa83a9eSThomas Graf  * nlmsg_put_answer - Add a new callback based netlink message to an skb
490bfa83a9eSThomas Graf  * @skb: socket buffer to store message in
491bfa83a9eSThomas Graf  * @cb: netlink callback
492bfa83a9eSThomas Graf  * @type: message type
493bfa83a9eSThomas Graf  * @payload: length of message payload
494bfa83a9eSThomas Graf  * @flags: message flags
495bfa83a9eSThomas Graf  *
496bfa83a9eSThomas Graf  * Returns NULL if the tailroom of the skb is insufficient to store
497bfa83a9eSThomas Graf  * the message header and payload.
498bfa83a9eSThomas Graf  */
499bfa83a9eSThomas Graf static inline struct nlmsghdr *nlmsg_put_answer(struct sk_buff *skb,
500bfa83a9eSThomas Graf 						struct netlink_callback *cb,
501bfa83a9eSThomas Graf 						int type, int payload,
502bfa83a9eSThomas Graf 						int flags)
503bfa83a9eSThomas Graf {
504bfa83a9eSThomas Graf 	return nlmsg_put(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,
505bfa83a9eSThomas Graf 			 type, payload, flags);
506bfa83a9eSThomas Graf }
507bfa83a9eSThomas Graf 
508bfa83a9eSThomas Graf /**
509bfa83a9eSThomas Graf  * nlmsg_new - Allocate a new netlink message
510339bf98fSThomas Graf  * @payload: size of the message payload
511fe4944e5SThomas Graf  * @flags: the type of memory to allocate.
512bfa83a9eSThomas Graf  *
513339bf98fSThomas Graf  * Use NLMSG_DEFAULT_SIZE if the size of the payload isn't known
514339bf98fSThomas Graf  * and a good default is needed.
515bfa83a9eSThomas Graf  */
516339bf98fSThomas Graf static inline struct sk_buff *nlmsg_new(size_t payload, gfp_t flags)
517bfa83a9eSThomas Graf {
518339bf98fSThomas Graf 	return alloc_skb(nlmsg_total_size(payload), flags);
519bfa83a9eSThomas Graf }
520bfa83a9eSThomas Graf 
521bfa83a9eSThomas Graf /**
522bfa83a9eSThomas Graf  * nlmsg_end - Finalize a netlink message
523bfa83a9eSThomas Graf  * @skb: socket buffer the message is stored in
524bfa83a9eSThomas Graf  * @nlh: netlink message header
525bfa83a9eSThomas Graf  *
526bfa83a9eSThomas Graf  * Corrects the netlink message header to include the appeneded
527bfa83a9eSThomas Graf  * attributes. Only necessary if attributes have been added to
528bfa83a9eSThomas Graf  * the message.
529bfa83a9eSThomas Graf  *
530bfa83a9eSThomas Graf  * Returns the total data length of the skb.
531bfa83a9eSThomas Graf  */
532bfa83a9eSThomas Graf static inline int nlmsg_end(struct sk_buff *skb, struct nlmsghdr *nlh)
533bfa83a9eSThomas Graf {
53427a884dcSArnaldo Carvalho de Melo 	nlh->nlmsg_len = skb_tail_pointer(skb) - (unsigned char *)nlh;
535bfa83a9eSThomas Graf 
536bfa83a9eSThomas Graf 	return skb->len;
537bfa83a9eSThomas Graf }
538bfa83a9eSThomas Graf 
539bfa83a9eSThomas Graf /**
540fe4944e5SThomas Graf  * nlmsg_get_pos - return current position in netlink message
541fe4944e5SThomas Graf  * @skb: socket buffer the message is stored in
542fe4944e5SThomas Graf  *
543fe4944e5SThomas Graf  * Returns a pointer to the current tail of the message.
544fe4944e5SThomas Graf  */
545fe4944e5SThomas Graf static inline void *nlmsg_get_pos(struct sk_buff *skb)
546fe4944e5SThomas Graf {
54727a884dcSArnaldo Carvalho de Melo 	return skb_tail_pointer(skb);
548fe4944e5SThomas Graf }
549fe4944e5SThomas Graf 
550fe4944e5SThomas Graf /**
551fe4944e5SThomas Graf  * nlmsg_trim - Trim message to a mark
552fe4944e5SThomas Graf  * @skb: socket buffer the message is stored in
553fe4944e5SThomas Graf  * @mark: mark to trim to
554fe4944e5SThomas Graf  *
555fe4944e5SThomas Graf  * Trims the message to the provided mark. Returns -1.
556fe4944e5SThomas Graf  */
557dc5fc579SArnaldo Carvalho de Melo static inline int nlmsg_trim(struct sk_buff *skb, const void *mark)
558fe4944e5SThomas Graf {
559fe4944e5SThomas Graf 	if (mark)
560fe4944e5SThomas Graf 		skb_trim(skb, (unsigned char *) mark - skb->data);
561fe4944e5SThomas Graf 
562fe4944e5SThomas Graf 	return -1;
563fe4944e5SThomas Graf }
564fe4944e5SThomas Graf 
565fe4944e5SThomas Graf /**
566bfa83a9eSThomas Graf  * nlmsg_cancel - Cancel construction of a netlink message
567bfa83a9eSThomas Graf  * @skb: socket buffer the message is stored in
568bfa83a9eSThomas Graf  * @nlh: netlink message header
569bfa83a9eSThomas Graf  *
570bfa83a9eSThomas Graf  * Removes the complete netlink message including all
571bfa83a9eSThomas Graf  * attributes from the socket buffer again. Returns -1.
572bfa83a9eSThomas Graf  */
573bfa83a9eSThomas Graf static inline int nlmsg_cancel(struct sk_buff *skb, struct nlmsghdr *nlh)
574bfa83a9eSThomas Graf {
575fe4944e5SThomas Graf 	return nlmsg_trim(skb, nlh);
576bfa83a9eSThomas Graf }
577bfa83a9eSThomas Graf 
578bfa83a9eSThomas Graf /**
579bfa83a9eSThomas Graf  * nlmsg_free - free a netlink message
580bfa83a9eSThomas Graf  * @skb: socket buffer of netlink message
581bfa83a9eSThomas Graf  */
582bfa83a9eSThomas Graf static inline void nlmsg_free(struct sk_buff *skb)
583bfa83a9eSThomas Graf {
584bfa83a9eSThomas Graf 	kfree_skb(skb);
585bfa83a9eSThomas Graf }
586bfa83a9eSThomas Graf 
587bfa83a9eSThomas Graf /**
588bfa83a9eSThomas Graf  * nlmsg_multicast - multicast a netlink message
589bfa83a9eSThomas Graf  * @sk: netlink socket to spread messages to
590bfa83a9eSThomas Graf  * @skb: netlink message as socket buffer
591bfa83a9eSThomas Graf  * @pid: own netlink pid to avoid sending to yourself
592bfa83a9eSThomas Graf  * @group: multicast group id
593d387f6adSThomas Graf  * @flags: allocation flags
594bfa83a9eSThomas Graf  */
595bfa83a9eSThomas Graf static inline int nlmsg_multicast(struct sock *sk, struct sk_buff *skb,
596d387f6adSThomas Graf 				  u32 pid, unsigned int group, gfp_t flags)
597bfa83a9eSThomas Graf {
598bfa83a9eSThomas Graf 	int err;
599bfa83a9eSThomas Graf 
600bfa83a9eSThomas Graf 	NETLINK_CB(skb).dst_group = group;
601bfa83a9eSThomas Graf 
602d387f6adSThomas Graf 	err = netlink_broadcast(sk, skb, pid, group, flags);
603bfa83a9eSThomas Graf 	if (err > 0)
604bfa83a9eSThomas Graf 		err = 0;
605bfa83a9eSThomas Graf 
606bfa83a9eSThomas Graf 	return err;
607bfa83a9eSThomas Graf }
608bfa83a9eSThomas Graf 
609bfa83a9eSThomas Graf /**
610bfa83a9eSThomas Graf  * nlmsg_unicast - unicast a netlink message
611bfa83a9eSThomas Graf  * @sk: netlink socket to spread message to
612bfa83a9eSThomas Graf  * @skb: netlink message as socket buffer
613bfa83a9eSThomas Graf  * @pid: netlink pid of the destination socket
614bfa83a9eSThomas Graf  */
615bfa83a9eSThomas Graf static inline int nlmsg_unicast(struct sock *sk, struct sk_buff *skb, u32 pid)
616bfa83a9eSThomas Graf {
617bfa83a9eSThomas Graf 	int err;
618bfa83a9eSThomas Graf 
619bfa83a9eSThomas Graf 	err = netlink_unicast(sk, skb, pid, MSG_DONTWAIT);
620bfa83a9eSThomas Graf 	if (err > 0)
621bfa83a9eSThomas Graf 		err = 0;
622bfa83a9eSThomas Graf 
623bfa83a9eSThomas Graf 	return err;
624bfa83a9eSThomas Graf }
625bfa83a9eSThomas Graf 
626bfa83a9eSThomas Graf /**
627bfa83a9eSThomas Graf  * nlmsg_for_each_msg - iterate over a stream of messages
628bfa83a9eSThomas Graf  * @pos: loop counter, set to current message
629bfa83a9eSThomas Graf  * @head: head of message stream
630bfa83a9eSThomas Graf  * @len: length of message stream
631bfa83a9eSThomas Graf  * @rem: initialized to len, holds bytes currently remaining in stream
632bfa83a9eSThomas Graf  */
633bfa83a9eSThomas Graf #define nlmsg_for_each_msg(pos, head, len, rem) \
634bfa83a9eSThomas Graf 	for (pos = head, rem = len; \
635bfa83a9eSThomas Graf 	     nlmsg_ok(pos, rem); \
636bfa83a9eSThomas Graf 	     pos = nlmsg_next(pos, &(rem)))
637bfa83a9eSThomas Graf 
638bfa83a9eSThomas Graf /**************************************************************************
639bfa83a9eSThomas Graf  * Netlink Attributes
640bfa83a9eSThomas Graf  **************************************************************************/
641bfa83a9eSThomas Graf 
642bfa83a9eSThomas Graf /**
643bfa83a9eSThomas Graf  * nla_attr_size - length of attribute not including padding
644bfa83a9eSThomas Graf  * @payload: length of payload
645bfa83a9eSThomas Graf  */
646bfa83a9eSThomas Graf static inline int nla_attr_size(int payload)
647bfa83a9eSThomas Graf {
648bfa83a9eSThomas Graf 	return NLA_HDRLEN + payload;
649bfa83a9eSThomas Graf }
650bfa83a9eSThomas Graf 
651bfa83a9eSThomas Graf /**
652bfa83a9eSThomas Graf  * nla_total_size - total length of attribute including padding
653bfa83a9eSThomas Graf  * @payload: length of payload
654bfa83a9eSThomas Graf  */
655bfa83a9eSThomas Graf static inline int nla_total_size(int payload)
656bfa83a9eSThomas Graf {
657bfa83a9eSThomas Graf 	return NLA_ALIGN(nla_attr_size(payload));
658bfa83a9eSThomas Graf }
659bfa83a9eSThomas Graf 
660bfa83a9eSThomas Graf /**
661bfa83a9eSThomas Graf  * nla_padlen - length of padding at the tail of attribute
662bfa83a9eSThomas Graf  * @payload: length of payload
663bfa83a9eSThomas Graf  */
664bfa83a9eSThomas Graf static inline int nla_padlen(int payload)
665bfa83a9eSThomas Graf {
666bfa83a9eSThomas Graf 	return nla_total_size(payload) - nla_attr_size(payload);
667bfa83a9eSThomas Graf }
668bfa83a9eSThomas Graf 
669bfa83a9eSThomas Graf /**
6708f4c1f9bSThomas Graf  * nla_type - attribute type
6718f4c1f9bSThomas Graf  * @nla: netlink attribute
6728f4c1f9bSThomas Graf  */
6738f4c1f9bSThomas Graf static inline int nla_type(const struct nlattr *nla)
6748f4c1f9bSThomas Graf {
6758f4c1f9bSThomas Graf 	return nla->nla_type & NLA_TYPE_MASK;
6768f4c1f9bSThomas Graf }
6778f4c1f9bSThomas Graf 
6788f4c1f9bSThomas Graf /**
679bfa83a9eSThomas Graf  * nla_data - head of payload
680bfa83a9eSThomas Graf  * @nla: netlink attribute
681bfa83a9eSThomas Graf  */
682bfa83a9eSThomas Graf static inline void *nla_data(const struct nlattr *nla)
683bfa83a9eSThomas Graf {
684bfa83a9eSThomas Graf 	return (char *) nla + NLA_HDRLEN;
685bfa83a9eSThomas Graf }
686bfa83a9eSThomas Graf 
687bfa83a9eSThomas Graf /**
688bfa83a9eSThomas Graf  * nla_len - length of payload
689bfa83a9eSThomas Graf  * @nla: netlink attribute
690bfa83a9eSThomas Graf  */
691bfa83a9eSThomas Graf static inline int nla_len(const struct nlattr *nla)
692bfa83a9eSThomas Graf {
693bfa83a9eSThomas Graf 	return nla->nla_len - NLA_HDRLEN;
694bfa83a9eSThomas Graf }
695bfa83a9eSThomas Graf 
696bfa83a9eSThomas Graf /**
697bfa83a9eSThomas Graf  * nla_ok - check if the netlink attribute fits into the remaining bytes
698bfa83a9eSThomas Graf  * @nla: netlink attribute
699bfa83a9eSThomas Graf  * @remaining: number of bytes remaining in attribute stream
700bfa83a9eSThomas Graf  */
701bfa83a9eSThomas Graf static inline int nla_ok(const struct nlattr *nla, int remaining)
702bfa83a9eSThomas Graf {
703bfa83a9eSThomas Graf 	return remaining >= sizeof(*nla) &&
704bfa83a9eSThomas Graf 	       nla->nla_len >= sizeof(*nla) &&
705bfa83a9eSThomas Graf 	       nla->nla_len <= remaining;
706bfa83a9eSThomas Graf }
707bfa83a9eSThomas Graf 
708bfa83a9eSThomas Graf /**
709d1ec3b77SPierre Ynard  * nla_next - next netlink attribute in attribute stream
710bfa83a9eSThomas Graf  * @nla: netlink attribute
711bfa83a9eSThomas Graf  * @remaining: number of bytes remaining in attribute stream
712bfa83a9eSThomas Graf  *
713bfa83a9eSThomas Graf  * Returns the next netlink attribute in the attribute stream and
714bfa83a9eSThomas Graf  * decrements remaining by the size of the current attribute.
715bfa83a9eSThomas Graf  */
716bfa83a9eSThomas Graf static inline struct nlattr *nla_next(const struct nlattr *nla, int *remaining)
717bfa83a9eSThomas Graf {
718bfa83a9eSThomas Graf 	int totlen = NLA_ALIGN(nla->nla_len);
719bfa83a9eSThomas Graf 
720bfa83a9eSThomas Graf 	*remaining -= totlen;
721bfa83a9eSThomas Graf 	return (struct nlattr *) ((char *) nla + totlen);
722bfa83a9eSThomas Graf }
723bfa83a9eSThomas Graf 
724bfa83a9eSThomas Graf /**
725fe4944e5SThomas Graf  * nla_find_nested - find attribute in a set of nested attributes
726fe4944e5SThomas Graf  * @nla: attribute containing the nested attributes
727fe4944e5SThomas Graf  * @attrtype: type of attribute to look for
728fe4944e5SThomas Graf  *
729fe4944e5SThomas Graf  * Returns the first attribute which matches the specified type.
730fe4944e5SThomas Graf  */
731fe4944e5SThomas Graf static inline struct nlattr *nla_find_nested(struct nlattr *nla, int attrtype)
732fe4944e5SThomas Graf {
733fe4944e5SThomas Graf 	return nla_find(nla_data(nla), nla_len(nla), attrtype);
734fe4944e5SThomas Graf }
735fe4944e5SThomas Graf 
736fe4944e5SThomas Graf /**
737bfa83a9eSThomas Graf  * nla_parse_nested - parse nested attributes
738bfa83a9eSThomas Graf  * @tb: destination array with maxtype+1 elements
739bfa83a9eSThomas Graf  * @maxtype: maximum attribute type to be expected
740bfa83a9eSThomas Graf  * @nla: attribute containing the nested attributes
741bfa83a9eSThomas Graf  * @policy: validation policy
742bfa83a9eSThomas Graf  *
743bfa83a9eSThomas Graf  * See nla_parse()
744bfa83a9eSThomas Graf  */
745bfa83a9eSThomas Graf static inline int nla_parse_nested(struct nlattr *tb[], int maxtype,
746bfa83a9eSThomas Graf 				   struct nlattr *nla,
747ef7c79edSPatrick McHardy 				   const struct nla_policy *policy)
748bfa83a9eSThomas Graf {
749bfa83a9eSThomas Graf 	return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
750bfa83a9eSThomas Graf }
7511092cb21SPatrick McHardy 
7521092cb21SPatrick McHardy /**
7531092cb21SPatrick McHardy  * nla_parse_nested_compat - parse nested compat attributes
7541092cb21SPatrick McHardy  * @tb: destination array with maxtype+1 elements
7551092cb21SPatrick McHardy  * @maxtype: maximum attribute type to be expected
7561092cb21SPatrick McHardy  * @nla: attribute containing the nested attributes
7571092cb21SPatrick McHardy  * @data: pointer to point to contained structure
7581092cb21SPatrick McHardy  * @len: length of contained structure
7591092cb21SPatrick McHardy  * @policy: validation policy
7601092cb21SPatrick McHardy  *
7611092cb21SPatrick McHardy  * Parse a nested compat attribute. The compat attribute contains a structure
7621092cb21SPatrick McHardy  * and optionally a set of nested attributes. On success the data pointer
7631092cb21SPatrick McHardy  * points to the nested data and tb contains the parsed attributes
7641092cb21SPatrick McHardy  * (see nla_parse).
7651092cb21SPatrick McHardy  */
7661092cb21SPatrick McHardy static inline int __nla_parse_nested_compat(struct nlattr *tb[], int maxtype,
7671092cb21SPatrick McHardy 					    struct nlattr *nla,
7681092cb21SPatrick McHardy 					    const struct nla_policy *policy,
7691092cb21SPatrick McHardy 					    int len)
7701092cb21SPatrick McHardy {
7711092cb21SPatrick McHardy 	if (nla_len(nla) < len)
7721092cb21SPatrick McHardy 		return -1;
7731092cb21SPatrick McHardy 	if (nla_len(nla) >= NLA_ALIGN(len) + sizeof(struct nlattr))
7741092cb21SPatrick McHardy 		return nla_parse_nested(tb, maxtype,
7751092cb21SPatrick McHardy 					nla_data(nla) + NLA_ALIGN(len),
7761092cb21SPatrick McHardy 					policy);
7771092cb21SPatrick McHardy 	memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
7781092cb21SPatrick McHardy 	return 0;
7791092cb21SPatrick McHardy }
7801092cb21SPatrick McHardy 
7811092cb21SPatrick McHardy #define nla_parse_nested_compat(tb, maxtype, nla, policy, data, len) \
7821092cb21SPatrick McHardy ({	data = nla_len(nla) >= len ? nla_data(nla) : NULL; \
7831092cb21SPatrick McHardy 	__nla_parse_nested_compat(tb, maxtype, nla, policy, len); })
784bfa83a9eSThomas Graf /**
785d1ec3b77SPierre Ynard  * nla_put_u8 - Add a u8 netlink attribute to a socket buffer
786bfa83a9eSThomas Graf  * @skb: socket buffer to add attribute to
787bfa83a9eSThomas Graf  * @attrtype: attribute type
788bfa83a9eSThomas Graf  * @value: numeric value
789bfa83a9eSThomas Graf  */
790bfa83a9eSThomas Graf static inline int nla_put_u8(struct sk_buff *skb, int attrtype, u8 value)
791bfa83a9eSThomas Graf {
792bfa83a9eSThomas Graf 	return nla_put(skb, attrtype, sizeof(u8), &value);
793bfa83a9eSThomas Graf }
794bfa83a9eSThomas Graf 
795bfa83a9eSThomas Graf /**
796bfa83a9eSThomas Graf  * nla_put_u16 - Add a u16 netlink attribute to a socket buffer
797bfa83a9eSThomas Graf  * @skb: socket buffer to add attribute to
798bfa83a9eSThomas Graf  * @attrtype: attribute type
799bfa83a9eSThomas Graf  * @value: numeric value
800bfa83a9eSThomas Graf  */
801bfa83a9eSThomas Graf static inline int nla_put_u16(struct sk_buff *skb, int attrtype, u16 value)
802bfa83a9eSThomas Graf {
803bfa83a9eSThomas Graf 	return nla_put(skb, attrtype, sizeof(u16), &value);
804bfa83a9eSThomas Graf }
805bfa83a9eSThomas Graf 
806bfa83a9eSThomas Graf /**
807bfa83a9eSThomas Graf  * nla_put_u32 - Add a u32 netlink attribute to a socket buffer
808bfa83a9eSThomas Graf  * @skb: socket buffer to add attribute to
809bfa83a9eSThomas Graf  * @attrtype: attribute type
810bfa83a9eSThomas Graf  * @value: numeric value
811bfa83a9eSThomas Graf  */
812bfa83a9eSThomas Graf static inline int nla_put_u32(struct sk_buff *skb, int attrtype, u32 value)
813bfa83a9eSThomas Graf {
814bfa83a9eSThomas Graf 	return nla_put(skb, attrtype, sizeof(u32), &value);
815bfa83a9eSThomas Graf }
816bfa83a9eSThomas Graf 
817bfa83a9eSThomas Graf /**
818bfa83a9eSThomas Graf  * nla_put_64 - Add a u64 netlink attribute to a socket buffer
819bfa83a9eSThomas Graf  * @skb: socket buffer to add attribute to
820bfa83a9eSThomas Graf  * @attrtype: attribute type
821bfa83a9eSThomas Graf  * @value: numeric value
822bfa83a9eSThomas Graf  */
823bfa83a9eSThomas Graf static inline int nla_put_u64(struct sk_buff *skb, int attrtype, u64 value)
824bfa83a9eSThomas Graf {
825bfa83a9eSThomas Graf 	return nla_put(skb, attrtype, sizeof(u64), &value);
826bfa83a9eSThomas Graf }
827bfa83a9eSThomas Graf 
828bfa83a9eSThomas Graf /**
829bfa83a9eSThomas Graf  * nla_put_string - Add a string netlink attribute to a socket buffer
830bfa83a9eSThomas Graf  * @skb: socket buffer to add attribute to
831bfa83a9eSThomas Graf  * @attrtype: attribute type
832bfa83a9eSThomas Graf  * @str: NUL terminated string
833bfa83a9eSThomas Graf  */
834bfa83a9eSThomas Graf static inline int nla_put_string(struct sk_buff *skb, int attrtype,
835bfa83a9eSThomas Graf 				 const char *str)
836bfa83a9eSThomas Graf {
837bfa83a9eSThomas Graf 	return nla_put(skb, attrtype, strlen(str) + 1, str);
838bfa83a9eSThomas Graf }
839bfa83a9eSThomas Graf 
840bfa83a9eSThomas Graf /**
841bfa83a9eSThomas Graf  * nla_put_flag - Add a flag netlink attribute to a socket buffer
842bfa83a9eSThomas Graf  * @skb: socket buffer to add attribute to
843bfa83a9eSThomas Graf  * @attrtype: attribute type
844bfa83a9eSThomas Graf  */
845bfa83a9eSThomas Graf static inline int nla_put_flag(struct sk_buff *skb, int attrtype)
846bfa83a9eSThomas Graf {
847bfa83a9eSThomas Graf 	return nla_put(skb, attrtype, 0, NULL);
848bfa83a9eSThomas Graf }
849bfa83a9eSThomas Graf 
850bfa83a9eSThomas Graf /**
851bfa83a9eSThomas Graf  * nla_put_msecs - Add a msecs netlink attribute to a socket buffer
852bfa83a9eSThomas Graf  * @skb: socket buffer to add attribute to
853bfa83a9eSThomas Graf  * @attrtype: attribute type
854bfa83a9eSThomas Graf  * @jiffies: number of msecs in jiffies
855bfa83a9eSThomas Graf  */
856bfa83a9eSThomas Graf static inline int nla_put_msecs(struct sk_buff *skb, int attrtype,
857bfa83a9eSThomas Graf 				unsigned long jiffies)
858bfa83a9eSThomas Graf {
859bfa83a9eSThomas Graf 	u64 tmp = jiffies_to_msecs(jiffies);
860bfa83a9eSThomas Graf 	return nla_put(skb, attrtype, sizeof(u64), &tmp);
861bfa83a9eSThomas Graf }
862bfa83a9eSThomas Graf 
863bfa83a9eSThomas Graf #define NLA_PUT(skb, attrtype, attrlen, data) \
864bfa83a9eSThomas Graf 	do { \
865bfa83a9eSThomas Graf 		if (nla_put(skb, attrtype, attrlen, data) < 0) \
866bfa83a9eSThomas Graf 			goto nla_put_failure; \
867bfa83a9eSThomas Graf 	} while(0)
868bfa83a9eSThomas Graf 
869bfa83a9eSThomas Graf #define NLA_PUT_TYPE(skb, type, attrtype, value) \
870bfa83a9eSThomas Graf 	do { \
871bfa83a9eSThomas Graf 		type __tmp = value; \
872bfa83a9eSThomas Graf 		NLA_PUT(skb, attrtype, sizeof(type), &__tmp); \
873bfa83a9eSThomas Graf 	} while(0)
874bfa83a9eSThomas Graf 
875bfa83a9eSThomas Graf #define NLA_PUT_U8(skb, attrtype, value) \
876bfa83a9eSThomas Graf 	NLA_PUT_TYPE(skb, u8, attrtype, value)
877bfa83a9eSThomas Graf 
878bfa83a9eSThomas Graf #define NLA_PUT_U16(skb, attrtype, value) \
879bfa83a9eSThomas Graf 	NLA_PUT_TYPE(skb, u16, attrtype, value)
880bfa83a9eSThomas Graf 
8814a89c256SThomas Graf #define NLA_PUT_LE16(skb, attrtype, value) \
8824a89c256SThomas Graf 	NLA_PUT_TYPE(skb, __le16, attrtype, value)
8834a89c256SThomas Graf 
884bfa83a9eSThomas Graf #define NLA_PUT_U32(skb, attrtype, value) \
885bfa83a9eSThomas Graf 	NLA_PUT_TYPE(skb, u32, attrtype, value)
886bfa83a9eSThomas Graf 
88700012e5bSAl Viro #define NLA_PUT_BE32(skb, attrtype, value) \
88800012e5bSAl Viro 	NLA_PUT_TYPE(skb, __be32, attrtype, value)
88900012e5bSAl Viro 
890bfa83a9eSThomas Graf #define NLA_PUT_U64(skb, attrtype, value) \
891bfa83a9eSThomas Graf 	NLA_PUT_TYPE(skb, u64, attrtype, value)
892bfa83a9eSThomas Graf 
893bfa83a9eSThomas Graf #define NLA_PUT_STRING(skb, attrtype, value) \
894bfa83a9eSThomas Graf 	NLA_PUT(skb, attrtype, strlen(value) + 1, value)
895bfa83a9eSThomas Graf 
896ff5dfe73SJohannes Berg #define NLA_PUT_FLAG(skb, attrtype) \
897bfa83a9eSThomas Graf 	NLA_PUT(skb, attrtype, 0, NULL)
898bfa83a9eSThomas Graf 
899bfa83a9eSThomas Graf #define NLA_PUT_MSECS(skb, attrtype, jiffies) \
900bfa83a9eSThomas Graf 	NLA_PUT_U64(skb, attrtype, jiffies_to_msecs(jiffies))
901bfa83a9eSThomas Graf 
902bfa83a9eSThomas Graf /**
903bfa83a9eSThomas Graf  * nla_get_u32 - return payload of u32 attribute
904bfa83a9eSThomas Graf  * @nla: u32 netlink attribute
905bfa83a9eSThomas Graf  */
906bfa83a9eSThomas Graf static inline u32 nla_get_u32(struct nlattr *nla)
907bfa83a9eSThomas Graf {
908bfa83a9eSThomas Graf 	return *(u32 *) nla_data(nla);
909bfa83a9eSThomas Graf }
910bfa83a9eSThomas Graf 
911bfa83a9eSThomas Graf /**
91200012e5bSAl Viro  * nla_get_be32 - return payload of __be32 attribute
91300012e5bSAl Viro  * @nla: __be32 netlink attribute
91400012e5bSAl Viro  */
91500012e5bSAl Viro static inline __be32 nla_get_be32(struct nlattr *nla)
91600012e5bSAl Viro {
91700012e5bSAl Viro 	return *(__be32 *) nla_data(nla);
91800012e5bSAl Viro }
91900012e5bSAl Viro 
92000012e5bSAl Viro /**
921bfa83a9eSThomas Graf  * nla_get_u16 - return payload of u16 attribute
922bfa83a9eSThomas Graf  * @nla: u16 netlink attribute
923bfa83a9eSThomas Graf  */
924bfa83a9eSThomas Graf static inline u16 nla_get_u16(struct nlattr *nla)
925bfa83a9eSThomas Graf {
926bfa83a9eSThomas Graf 	return *(u16 *) nla_data(nla);
927bfa83a9eSThomas Graf }
928bfa83a9eSThomas Graf 
929bfa83a9eSThomas Graf /**
9304a89c256SThomas Graf  * nla_get_le16 - return payload of __le16 attribute
9314a89c256SThomas Graf  * @nla: __le16 netlink attribute
9324a89c256SThomas Graf  */
9334a89c256SThomas Graf static inline __le16 nla_get_le16(struct nlattr *nla)
9344a89c256SThomas Graf {
9354a89c256SThomas Graf 	return *(__le16 *) nla_data(nla);
9364a89c256SThomas Graf }
9374a89c256SThomas Graf 
9384a89c256SThomas Graf /**
939bfa83a9eSThomas Graf  * nla_get_u8 - return payload of u8 attribute
940bfa83a9eSThomas Graf  * @nla: u8 netlink attribute
941bfa83a9eSThomas Graf  */
942bfa83a9eSThomas Graf static inline u8 nla_get_u8(struct nlattr *nla)
943bfa83a9eSThomas Graf {
944bfa83a9eSThomas Graf 	return *(u8 *) nla_data(nla);
945bfa83a9eSThomas Graf }
946bfa83a9eSThomas Graf 
947bfa83a9eSThomas Graf /**
948bfa83a9eSThomas Graf  * nla_get_u64 - return payload of u64 attribute
949bfa83a9eSThomas Graf  * @nla: u64 netlink attribute
950bfa83a9eSThomas Graf  */
951bfa83a9eSThomas Graf static inline u64 nla_get_u64(struct nlattr *nla)
952bfa83a9eSThomas Graf {
953bfa83a9eSThomas Graf 	u64 tmp;
954bfa83a9eSThomas Graf 
955bfa83a9eSThomas Graf 	nla_memcpy(&tmp, nla, sizeof(tmp));
956bfa83a9eSThomas Graf 
957bfa83a9eSThomas Graf 	return tmp;
958bfa83a9eSThomas Graf }
959bfa83a9eSThomas Graf 
960bfa83a9eSThomas Graf /**
961bfa83a9eSThomas Graf  * nla_get_flag - return payload of flag attribute
962bfa83a9eSThomas Graf  * @nla: flag netlink attribute
963bfa83a9eSThomas Graf  */
964bfa83a9eSThomas Graf static inline int nla_get_flag(struct nlattr *nla)
965bfa83a9eSThomas Graf {
966bfa83a9eSThomas Graf 	return !!nla;
967bfa83a9eSThomas Graf }
968bfa83a9eSThomas Graf 
969bfa83a9eSThomas Graf /**
970bfa83a9eSThomas Graf  * nla_get_msecs - return payload of msecs attribute
971bfa83a9eSThomas Graf  * @nla: msecs netlink attribute
972bfa83a9eSThomas Graf  *
973bfa83a9eSThomas Graf  * Returns the number of milliseconds in jiffies.
974bfa83a9eSThomas Graf  */
975bfa83a9eSThomas Graf static inline unsigned long nla_get_msecs(struct nlattr *nla)
976bfa83a9eSThomas Graf {
977bfa83a9eSThomas Graf 	u64 msecs = nla_get_u64(nla);
978bfa83a9eSThomas Graf 
979bfa83a9eSThomas Graf 	return msecs_to_jiffies((unsigned long) msecs);
980bfa83a9eSThomas Graf }
981bfa83a9eSThomas Graf 
982bfa83a9eSThomas Graf /**
983bfa83a9eSThomas Graf  * nla_nest_start - Start a new level of nested attributes
984bfa83a9eSThomas Graf  * @skb: socket buffer to add attributes to
985bfa83a9eSThomas Graf  * @attrtype: attribute type of container
986bfa83a9eSThomas Graf  *
987bfa83a9eSThomas Graf  * Returns the container attribute
988bfa83a9eSThomas Graf  */
989bfa83a9eSThomas Graf static inline struct nlattr *nla_nest_start(struct sk_buff *skb, int attrtype)
990bfa83a9eSThomas Graf {
99127a884dcSArnaldo Carvalho de Melo 	struct nlattr *start = (struct nlattr *)skb_tail_pointer(skb);
992bfa83a9eSThomas Graf 
993bfa83a9eSThomas Graf 	if (nla_put(skb, attrtype, 0, NULL) < 0)
994bfa83a9eSThomas Graf 		return NULL;
995bfa83a9eSThomas Graf 
996bfa83a9eSThomas Graf 	return start;
997bfa83a9eSThomas Graf }
998bfa83a9eSThomas Graf 
999bfa83a9eSThomas Graf /**
1000bfa83a9eSThomas Graf  * nla_nest_end - Finalize nesting of attributes
1001d1ec3b77SPierre Ynard  * @skb: socket buffer the attributes are stored in
1002bfa83a9eSThomas Graf  * @start: container attribute
1003bfa83a9eSThomas Graf  *
1004bfa83a9eSThomas Graf  * Corrects the container attribute header to include the all
1005bfa83a9eSThomas Graf  * appeneded attributes.
1006bfa83a9eSThomas Graf  *
1007bfa83a9eSThomas Graf  * Returns the total data length of the skb.
1008bfa83a9eSThomas Graf  */
1009bfa83a9eSThomas Graf static inline int nla_nest_end(struct sk_buff *skb, struct nlattr *start)
1010bfa83a9eSThomas Graf {
101127a884dcSArnaldo Carvalho de Melo 	start->nla_len = skb_tail_pointer(skb) - (unsigned char *)start;
1012bfa83a9eSThomas Graf 	return skb->len;
1013bfa83a9eSThomas Graf }
1014bfa83a9eSThomas Graf 
1015bfa83a9eSThomas Graf /**
10161092cb21SPatrick McHardy  * nla_nest_compat_start - Start a new level of nested compat attributes
10171092cb21SPatrick McHardy  * @skb: socket buffer to add attributes to
10181092cb21SPatrick McHardy  * @attrtype: attribute type of container
10191092cb21SPatrick McHardy  * @attrlen: length of structure
10201092cb21SPatrick McHardy  * @data: pointer to structure
10211092cb21SPatrick McHardy  *
10221092cb21SPatrick McHardy  * Start a nested compat attribute that contains both a structure and
10231092cb21SPatrick McHardy  * a set of nested attributes.
10241092cb21SPatrick McHardy  *
10251092cb21SPatrick McHardy  * Returns the container attribute
10261092cb21SPatrick McHardy  */
10271092cb21SPatrick McHardy static inline struct nlattr *nla_nest_compat_start(struct sk_buff *skb,
10281092cb21SPatrick McHardy 						   int attrtype, int attrlen,
10291092cb21SPatrick McHardy 						   const void *data)
10301092cb21SPatrick McHardy {
10311092cb21SPatrick McHardy 	struct nlattr *start = (struct nlattr *)skb_tail_pointer(skb);
10321092cb21SPatrick McHardy 
10331092cb21SPatrick McHardy 	if (nla_put(skb, attrtype, attrlen, data) < 0)
10341092cb21SPatrick McHardy 		return NULL;
10351092cb21SPatrick McHardy 	if (nla_nest_start(skb, attrtype) == NULL) {
10361092cb21SPatrick McHardy 		nlmsg_trim(skb, start);
10371092cb21SPatrick McHardy 		return NULL;
10381092cb21SPatrick McHardy 	}
10391092cb21SPatrick McHardy 	return start;
10401092cb21SPatrick McHardy }
10411092cb21SPatrick McHardy 
10421092cb21SPatrick McHardy /**
10431092cb21SPatrick McHardy  * nla_nest_compat_end - Finalize nesting of compat attributes
1044d1ec3b77SPierre Ynard  * @skb: socket buffer the attributes are stored in
10451092cb21SPatrick McHardy  * @start: container attribute
10461092cb21SPatrick McHardy  *
10471092cb21SPatrick McHardy  * Corrects the container attribute header to include the all
10481092cb21SPatrick McHardy  * appeneded attributes.
10491092cb21SPatrick McHardy  *
10501092cb21SPatrick McHardy  * Returns the total data length of the skb.
10511092cb21SPatrick McHardy  */
10521092cb21SPatrick McHardy static inline int nla_nest_compat_end(struct sk_buff *skb, struct nlattr *start)
10531092cb21SPatrick McHardy {
10541092cb21SPatrick McHardy 	struct nlattr *nest = (void *)start + NLMSG_ALIGN(start->nla_len);
10551092cb21SPatrick McHardy 
10561092cb21SPatrick McHardy 	start->nla_len = skb_tail_pointer(skb) - (unsigned char *)start;
10571092cb21SPatrick McHardy 	return nla_nest_end(skb, nest);
10581092cb21SPatrick McHardy }
10591092cb21SPatrick McHardy 
10601092cb21SPatrick McHardy /**
1061bfa83a9eSThomas Graf  * nla_nest_cancel - Cancel nesting of attributes
1062bfa83a9eSThomas Graf  * @skb: socket buffer the message is stored in
1063bfa83a9eSThomas Graf  * @start: container attribute
1064bfa83a9eSThomas Graf  *
1065bfa83a9eSThomas Graf  * Removes the container attribute and including all nested
1066bfa83a9eSThomas Graf  * attributes. Returns -1.
1067bfa83a9eSThomas Graf  */
1068bfa83a9eSThomas Graf static inline int nla_nest_cancel(struct sk_buff *skb, struct nlattr *start)
1069bfa83a9eSThomas Graf {
1070fe4944e5SThomas Graf 	return nlmsg_trim(skb, start);
1071bfa83a9eSThomas Graf }
1072bfa83a9eSThomas Graf 
1073bfa83a9eSThomas Graf /**
10744fe5d5c0SPaul Moore  * nla_validate_nested - Validate a stream of nested attributes
10754fe5d5c0SPaul Moore  * @start: container attribute
10764fe5d5c0SPaul Moore  * @maxtype: maximum attribute type to be expected
10774fe5d5c0SPaul Moore  * @policy: validation policy
10784fe5d5c0SPaul Moore  *
10794fe5d5c0SPaul Moore  * Validates all attributes in the nested attribute stream against the
10804fe5d5c0SPaul Moore  * specified policy. Attributes with a type exceeding maxtype will be
10814fe5d5c0SPaul Moore  * ignored. See documenation of struct nla_policy for more details.
10824fe5d5c0SPaul Moore  *
10834fe5d5c0SPaul Moore  * Returns 0 on success or a negative error code.
10844fe5d5c0SPaul Moore  */
10854fe5d5c0SPaul Moore static inline int nla_validate_nested(struct nlattr *start, int maxtype,
1086ef7c79edSPatrick McHardy 				      const struct nla_policy *policy)
10874fe5d5c0SPaul Moore {
10884fe5d5c0SPaul Moore 	return nla_validate(nla_data(start), nla_len(start), maxtype, policy);
10894fe5d5c0SPaul Moore }
10904fe5d5c0SPaul Moore 
10914fe5d5c0SPaul Moore /**
1092bfa83a9eSThomas Graf  * nla_for_each_attr - iterate over a stream of attributes
1093bfa83a9eSThomas Graf  * @pos: loop counter, set to current attribute
1094bfa83a9eSThomas Graf  * @head: head of attribute stream
1095bfa83a9eSThomas Graf  * @len: length of attribute stream
1096bfa83a9eSThomas Graf  * @rem: initialized to len, holds bytes currently remaining in stream
1097bfa83a9eSThomas Graf  */
1098bfa83a9eSThomas Graf #define nla_for_each_attr(pos, head, len, rem) \
1099bfa83a9eSThomas Graf 	for (pos = head, rem = len; \
1100bfa83a9eSThomas Graf 	     nla_ok(pos, rem); \
1101bfa83a9eSThomas Graf 	     pos = nla_next(pos, &(rem)))
1102bfa83a9eSThomas Graf 
1103fe4944e5SThomas Graf /**
1104fe4944e5SThomas Graf  * nla_for_each_nested - iterate over nested attributes
1105fe4944e5SThomas Graf  * @pos: loop counter, set to current attribute
1106fe4944e5SThomas Graf  * @nla: attribute containing the nested attributes
1107fe4944e5SThomas Graf  * @rem: initialized to len, holds bytes currently remaining in stream
1108fe4944e5SThomas Graf  */
1109fe4944e5SThomas Graf #define nla_for_each_nested(pos, nla, rem) \
1110fe4944e5SThomas Graf 	nla_for_each_attr(pos, nla_data(nla), nla_len(nla), rem)
1111fe4944e5SThomas Graf 
1112bfa83a9eSThomas Graf #endif
1113