firmware-utils: move bcm_tag.h here
[openwrt.git] / package / libnl-tiny / src / include / netlink / msg.h
1 /*
2  * netlink/msg.c                Netlink Messages Interface
3  *
4  *      This library is free software; you can redistribute it and/or
5  *      modify it under the terms of the GNU Lesser General Public
6  *      License as published by the Free Software Foundation version 2.1
7  *      of the License.
8  *
9  * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
10  */
11
12 #ifndef NETLINK_MSG_H_
13 #define NETLINK_MSG_H_
14
15 #include <netlink/netlink.h>
16 #include <netlink/object.h>
17
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21
22 struct nla_policy;
23
24 #define NL_DONTPAD      0
25
26 /**
27  * @ingroup msg
28  * @brief
29  * Will cause the netlink pid to be set to the pid assigned to
30  * the netlink handle (socket) just before sending the message off.
31  * @note Requires the use of nl_send_auto_complete()!
32  */
33 #define NL_AUTO_PID     0
34
35 /**
36  * @ingroup msg
37  * @brief
38  * May be used to refer to a sequence number which should be
39  * automatically set just before sending the message off.
40  * @note Requires the use of nl_send_auto_complete()!
41  */
42 #define NL_AUTO_SEQ     0
43
44 #define NL_MSG_CRED_PRESENT 1
45
46 struct nl_msg
47 {
48         int                     nm_protocol;
49         int                     nm_flags;
50         struct sockaddr_nl      nm_src;
51         struct sockaddr_nl      nm_dst;
52         struct ucred            nm_creds;
53         struct nlmsghdr *       nm_nlh;
54         size_t                  nm_size;
55         int                     nm_refcnt;
56 };
57
58
59 struct nl_msg;
60 struct nl_tree;
61 struct ucred;
62
63 /* message parsing */
64 extern int                nlmsg_ok(const struct nlmsghdr *, int);
65 extern struct nlmsghdr *  nlmsg_next(struct nlmsghdr *, int *);
66 extern int                nlmsg_parse(struct nlmsghdr *, int, struct nlattr **,
67                                       int, struct nla_policy *);
68 extern int                nlmsg_validate(struct nlmsghdr *, int, int,
69                                          struct nla_policy *);
70
71 extern struct nl_msg *    nlmsg_alloc(void);
72 extern struct nl_msg *    nlmsg_alloc_size(size_t);
73 extern struct nl_msg *    nlmsg_alloc_simple(int, int);
74 extern void               nlmsg_set_default_size(size_t);
75 extern struct nl_msg *    nlmsg_inherit(struct nlmsghdr *);
76 extern struct nl_msg *    nlmsg_convert(struct nlmsghdr *);
77 extern void *             nlmsg_reserve(struct nl_msg *, size_t, int);
78 extern int                nlmsg_append(struct nl_msg *, void *, size_t, int);
79
80 extern struct nlmsghdr *  nlmsg_put(struct nl_msg *, uint32_t, uint32_t,
81                                     int, int, int);
82 extern void               nlmsg_free(struct nl_msg *);
83
84 extern int                nl_msg_parse(struct nl_msg *,
85                                        void (*cb)(struct nl_object *, void *),
86                                        void *);
87
88 extern void             nl_msg_dump(struct nl_msg *, FILE *);
89
90 /**
91  * length of netlink message not including padding
92  * @arg payload         length of message payload
93  */
94 static inline int nlmsg_msg_size(int payload)
95 {
96         return NLMSG_HDRLEN + payload;
97 }
98
99 /**
100  * length of netlink message including padding
101  * @arg payload         length of message payload
102  */
103 static inline int nlmsg_total_size(int payload)
104 {
105         return NLMSG_ALIGN(nlmsg_msg_size(payload));
106 }
107
108 /**
109  * length of padding at the message's tail
110  * @arg payload         length of message payload
111  */
112 static inline int nlmsg_padlen(int payload)
113 {
114         return nlmsg_total_size(payload) - nlmsg_msg_size(payload);
115 }
116
117 /**
118  * head of message payload
119  * @arg nlh             netlink messsage header
120  */
121 static inline void *nlmsg_data(const struct nlmsghdr *nlh)
122 {
123         return (unsigned char *) nlh + NLMSG_HDRLEN;
124 }
125
126 static inline void *nlmsg_tail(const struct nlmsghdr *nlh)
127 {
128         return (unsigned char *) nlh + NLMSG_ALIGN(nlh->nlmsg_len);
129 }
130
131 /**
132  * length of message payload
133  * @arg nlh             netlink message header
134  */
135 static inline int nlmsg_len(const struct nlmsghdr *nlh)
136 {
137         return nlh->nlmsg_len - NLMSG_HDRLEN;
138 }
139
140 /**
141  * head of attributes data
142  * @arg nlh             netlink message header
143  * @arg hdrlen          length of family specific header
144  */
145 static inline struct nlattr *nlmsg_attrdata(const struct nlmsghdr *nlh, int hdrlen)
146 {
147         unsigned char *data = (unsigned char*)nlmsg_data(nlh);
148         return (struct nlattr *) (data + NLMSG_ALIGN(hdrlen));
149 }
150
151 /**
152  * length of attributes data
153  * @arg nlh             netlink message header
154  * @arg hdrlen          length of family specific header
155  */
156 static inline int nlmsg_attrlen(const struct nlmsghdr *nlh, int hdrlen)
157 {
158         return nlmsg_len(nlh) - NLMSG_ALIGN(hdrlen);
159 }
160
161 static inline int nlmsg_valid_hdr(const struct nlmsghdr *nlh, int hdrlen)
162 {
163         if (nlh->nlmsg_len < (uint)nlmsg_msg_size(hdrlen))
164                 return 0;
165
166         return 1;
167 }
168
169
170 static inline void nlmsg_set_proto(struct nl_msg *msg, int protocol)
171 {
172         msg->nm_protocol = protocol;
173 }
174
175 static inline int nlmsg_get_proto(struct nl_msg *msg)
176 {
177         return msg->nm_protocol;
178 }
179
180 static inline size_t nlmsg_get_max_size(struct nl_msg *msg)
181 {
182         return msg->nm_size;
183 }
184
185 static inline void nlmsg_set_src(struct nl_msg *msg, struct sockaddr_nl *addr)
186 {
187         memcpy(&msg->nm_src, addr, sizeof(*addr));
188 }
189
190 static inline struct sockaddr_nl *nlmsg_get_src(struct nl_msg *msg)
191 {
192         return &msg->nm_src;
193 }
194
195 static inline void nlmsg_set_dst(struct nl_msg *msg, struct sockaddr_nl *addr)
196 {
197         memcpy(&msg->nm_dst, addr, sizeof(*addr));
198 }
199
200 static inline struct sockaddr_nl *nlmsg_get_dst(struct nl_msg *msg)
201 {
202         return &msg->nm_dst;
203 }
204
205 static inline void nlmsg_set_creds(struct nl_msg *msg, struct ucred *creds)
206 {
207         memcpy(&msg->nm_creds, creds, sizeof(*creds));
208         msg->nm_flags |= NL_MSG_CRED_PRESENT;
209 }
210
211 static inline struct ucred *nlmsg_get_creds(struct nl_msg *msg)
212 {
213         if (msg->nm_flags & NL_MSG_CRED_PRESENT)
214                 return &msg->nm_creds;
215         return NULL;
216 }
217
218 /**
219  * Return actual netlink message
220  * @arg n               netlink message
221  * 
222  * Returns the actual netlink message casted to the type of the netlink
223  * message header.
224  * 
225  * @return A pointer to the netlink message.
226  */
227 static inline struct nlmsghdr *nlmsg_hdr(struct nl_msg *n)
228 {
229         return n->nm_nlh;
230 }
231
232 /**
233  * Acquire a reference on a netlink message
234  * @arg msg             message to acquire reference from
235  */
236 static inline void nlmsg_get(struct nl_msg *msg)
237 {
238         msg->nm_refcnt++;
239 }
240
241 /**
242  * Expand maximum payload size of a netlink message
243  * @arg n               Netlink message.
244  * @arg newlen          New maximum payload size.
245  *
246  * Reallocates the payload section of a netlink message and increases
247  * the maximum payload size of the message.
248  *
249  * @note Any pointers pointing to old payload block will be stale and
250  *       need to be refetched. Therfore, do not expand while constructing
251  *       nested attributes or while reserved data blocks are held.
252  *
253  * @return 0 on success or a negative error code.
254  */
255 static inline int nlmsg_expand(struct nl_msg *n, size_t newlen)
256 {
257         void *tmp;
258
259         if (newlen <= n->nm_size)
260                 return -NLE_INVAL;
261
262         tmp = realloc(n->nm_nlh, newlen);
263         if (tmp == NULL)
264                 return -NLE_NOMEM;
265
266         n->nm_nlh = (struct nlmsghdr*)tmp;
267         n->nm_size = newlen;
268
269         return 0;
270 }
271
272
273 /**
274  * @name Iterators
275  * @{
276  */
277
278 /**
279  * @ingroup msg
280  * Iterate over a stream of attributes in a message
281  * @arg pos     loop counter, set to current attribute
282  * @arg nlh     netlink message header
283  * @arg hdrlen  length of family header
284  * @arg rem     initialized to len, holds bytes currently remaining in stream
285  */
286 #define nlmsg_for_each_attr(pos, nlh, hdrlen, rem) \
287         nla_for_each_attr(pos, nlmsg_attrdata(nlh, hdrlen), \
288                           nlmsg_attrlen(nlh, hdrlen), rem)
289
290 /**
291  * Iterate over a stream of messages
292  * @arg pos     loop counter, set to current message
293  * @arg head    head of message stream
294  * @arg len     length of message stream
295  * @arg rem     initialized to len, holds bytes currently remaining in stream
296  */
297 #define nlmsg_for_each_msg(pos, head, len, rem) \
298         for (pos = head, rem = len; \
299              nlmsg_ok(pos, rem); \
300              pos = nlmsg_next(pos, &(rem)))
301
302 /** @} */
303
304 #ifdef __cplusplus
305 }
306 #endif
307
308 #endif