Tizen 2.1 base
[platform/upstream/libnl2.git] / lib / handlers.c
1 /*
2  * lib/handlers.c       default netlink message handlers
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 /**
13  * @ingroup core
14  * @defgroup cb Callbacks/Customization
15  *
16  * @details
17  * @par 1) Setting up a callback set
18  * @code
19  * // Allocate a callback set and initialize it to the verbose default set
20  * struct nl_cb *cb = nl_cb_alloc(NL_CB_VERBOSE);
21  *
22  * // Modify the set to call my_func() for all valid messages
23  * nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL);
24  *
25  * // Set the error message handler to the verbose default implementation
26  * // and direct it to print all errors to the given file descriptor.
27  * FILE *file = fopen(...);
28  * nl_cb_err(cb, NL_CB_VERBOSE, NULL, file);
29  * @endcode
30  * @{
31  */
32
33 #include <netlink-local.h>
34 #include <netlink/netlink.h>
35 #include <netlink/utils.h>
36 #include <netlink/msg.h>
37 #include <netlink/handlers.h>
38
39 static void print_header_content(FILE *ofd, struct nlmsghdr *n)
40 {
41         char flags[128];
42         char type[32];
43         
44         fprintf(ofd, "type=%s length=%u flags=<%s> sequence-nr=%u pid=%u",
45                 nl_nlmsgtype2str(n->nlmsg_type, type, sizeof(type)),
46                 n->nlmsg_len, nl_nlmsg_flags2str(n->nlmsg_flags, flags,
47                 sizeof(flags)), n->nlmsg_seq, n->nlmsg_pid);
48 }
49
50 static int nl_valid_handler_verbose(struct nl_msg *msg, void *arg)
51 {
52         FILE *ofd = arg ? arg : stdout;
53
54         fprintf(ofd, "-- Warning: unhandled valid message: ");
55         print_header_content(ofd, nlmsg_hdr(msg));
56         fprintf(ofd, "\n");
57
58         return NL_OK;
59 }
60
61 static int nl_invalid_handler_verbose(struct nl_msg *msg, void *arg)
62 {
63         FILE *ofd = arg ? arg : stderr;
64
65         fprintf(ofd, "-- Error: Invalid message: ");
66         print_header_content(ofd, nlmsg_hdr(msg));
67         fprintf(ofd, "\n");
68
69         return NL_STOP;
70 }
71
72 static int nl_overrun_handler_verbose(struct nl_msg *msg, void *arg)
73 {
74         FILE *ofd = arg ? arg : stderr;
75
76         fprintf(ofd, "-- Error: Netlink Overrun: ");
77         print_header_content(ofd, nlmsg_hdr(msg));
78         fprintf(ofd, "\n");
79         
80         return NL_STOP;
81 }
82
83 static int nl_error_handler_verbose(struct sockaddr_nl *who,
84                                     struct nlmsgerr *e, void *arg)
85 {
86         FILE *ofd = arg ? arg : stderr;
87
88         fprintf(ofd, "-- Error received: %s\n-- Original message: ",
89                 strerror(-e->error));
90         print_header_content(ofd, &e->msg);
91         fprintf(ofd, "\n");
92
93         return -nl_syserr2nlerr(e->error);
94 }
95
96 static int nl_valid_handler_debug(struct nl_msg *msg, void *arg)
97 {
98         FILE *ofd = arg ? arg : stderr;
99
100         fprintf(ofd, "-- Debug: Unhandled Valid message: ");
101         print_header_content(ofd, nlmsg_hdr(msg));
102         fprintf(ofd, "\n");
103
104         return NL_OK;
105 }
106
107 static int nl_finish_handler_debug(struct nl_msg *msg, void *arg)
108 {
109         FILE *ofd = arg ? arg : stderr;
110
111         fprintf(ofd, "-- Debug: End of multipart message block: ");
112         print_header_content(ofd, nlmsg_hdr(msg));
113         fprintf(ofd, "\n");
114         
115         return NL_STOP;
116 }
117
118 static int nl_msg_in_handler_debug(struct nl_msg *msg, void *arg)
119 {
120         FILE *ofd = arg ? arg : stderr;
121
122         fprintf(ofd, "-- Debug: Received Message:\n");
123         nl_msg_dump(msg, ofd);
124         
125         return NL_OK;
126 }
127
128 static int nl_msg_out_handler_debug(struct nl_msg *msg, void *arg)
129 {
130         FILE *ofd = arg ? arg : stderr;
131
132         fprintf(ofd, "-- Debug: Sent Message:\n");
133         nl_msg_dump(msg, ofd);
134
135         return NL_OK;
136 }
137
138 static int nl_skipped_handler_debug(struct nl_msg *msg, void *arg)
139 {
140         FILE *ofd = arg ? arg : stderr;
141
142         fprintf(ofd, "-- Debug: Skipped message: ");
143         print_header_content(ofd, nlmsg_hdr(msg));
144         fprintf(ofd, "\n");
145
146         return NL_SKIP;
147 }
148
149 static int nl_ack_handler_debug(struct nl_msg *msg, void *arg)
150 {
151         FILE *ofd = arg ? arg : stderr;
152
153         fprintf(ofd, "-- Debug: ACK: ");
154         print_header_content(ofd, nlmsg_hdr(msg));
155         fprintf(ofd, "\n");
156
157         return NL_STOP;
158 }
159
160 static nl_recvmsg_msg_cb_t cb_def[NL_CB_TYPE_MAX+1][NL_CB_KIND_MAX+1] = {
161         [NL_CB_VALID] = {
162                 [NL_CB_VERBOSE] = nl_valid_handler_verbose,
163                 [NL_CB_DEBUG]   = nl_valid_handler_debug,
164         },
165         [NL_CB_FINISH] = {
166                 [NL_CB_DEBUG]   = nl_finish_handler_debug,
167         },
168         [NL_CB_INVALID] = {
169                 [NL_CB_VERBOSE] = nl_invalid_handler_verbose,
170                 [NL_CB_DEBUG]   = nl_invalid_handler_verbose,
171         },
172         [NL_CB_MSG_IN] = {
173                 [NL_CB_DEBUG]   = nl_msg_in_handler_debug,
174         },
175         [NL_CB_MSG_OUT] = {
176                 [NL_CB_DEBUG]   = nl_msg_out_handler_debug,
177         },
178         [NL_CB_OVERRUN] = {
179                 [NL_CB_VERBOSE] = nl_overrun_handler_verbose,
180                 [NL_CB_DEBUG]   = nl_overrun_handler_verbose,
181         },
182         [NL_CB_SKIPPED] = {
183                 [NL_CB_DEBUG]   = nl_skipped_handler_debug,
184         },
185         [NL_CB_ACK] = {
186                 [NL_CB_DEBUG]   = nl_ack_handler_debug,
187         },
188 };
189
190 static nl_recvmsg_err_cb_t cb_err_def[NL_CB_KIND_MAX+1] = {
191         [NL_CB_VERBOSE] = nl_error_handler_verbose,
192         [NL_CB_DEBUG]   = nl_error_handler_verbose,
193 };
194
195 /**
196  * @name Callback Handle Management
197  * @{
198  */
199
200 /**
201  * Allocate a new callback handle
202  * @arg kind            callback kind to be used for initialization
203  * @return Newly allocated callback handle or NULL
204  */
205 struct nl_cb *nl_cb_alloc(enum nl_cb_kind kind)
206 {
207         int i;
208         struct nl_cb *cb;
209
210         if (kind < 0 || kind > NL_CB_KIND_MAX)
211                 return NULL;
212
213         cb = calloc(1, sizeof(*cb));
214         if (!cb)
215                 return NULL;
216
217         cb->cb_refcnt = 1;
218
219         for (i = 0; i <= NL_CB_TYPE_MAX; i++)
220                 nl_cb_set(cb, i, kind, NULL, NULL);
221
222         nl_cb_err(cb, kind, NULL, NULL);
223
224         return cb;
225 }
226
227 /**
228  * Clone an existing callback handle
229  * @arg orig            original callback handle
230  * @return Newly allocated callback handle being a duplicate of
231  *         orig or NULL
232  */
233 struct nl_cb *nl_cb_clone(struct nl_cb *orig)
234 {
235         struct nl_cb *cb;
236         
237         cb = nl_cb_alloc(NL_CB_DEFAULT);
238         if (!cb)
239                 return NULL;
240
241         memcpy(cb, orig, sizeof(*orig));
242         cb->cb_refcnt = 1;
243
244         return cb;
245 }
246
247 struct nl_cb *nl_cb_get(struct nl_cb *cb)
248 {
249         cb->cb_refcnt++;
250
251         return cb;
252 }
253
254 void nl_cb_put(struct nl_cb *cb)
255 {
256         if (!cb)
257                 return;
258
259         cb->cb_refcnt--;
260
261         if (cb->cb_refcnt < 0)
262                 BUG();
263
264         if (cb->cb_refcnt <= 0)
265                 free(cb);
266 }
267
268 /** @} */
269
270 /**
271  * @name Callback Setup
272  * @{
273  */
274
275 /**
276  * Set up a callback 
277  * @arg cb              callback set
278  * @arg type            callback to modify
279  * @arg kind            kind of implementation
280  * @arg func            callback function (NL_CB_CUSTOM)
281  * @arg arg             argument passed to callback
282  *
283  * @return 0 on success or a negative error code
284  */
285 int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind,
286               nl_recvmsg_msg_cb_t func, void *arg)
287 {
288         if (type < 0 || type > NL_CB_TYPE_MAX)
289                 return -NLE_RANGE;
290
291         if (kind < 0 || kind > NL_CB_KIND_MAX)
292                 return -NLE_RANGE;
293
294         if (kind == NL_CB_CUSTOM) {
295                 cb->cb_set[type] = func;
296                 cb->cb_args[type] = arg;
297         } else {
298                 cb->cb_set[type] = cb_def[type][kind];
299                 cb->cb_args[type] = arg;
300         }
301
302         return 0;
303 }
304
305 /**
306  * Set up a all callbacks
307  * @arg cb              callback set
308  * @arg kind            kind of callback
309  * @arg func            callback function
310  * @arg arg             argument to be passwd to callback function
311  *
312  * @return 0 on success or a negative error code
313  */
314 int nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind,
315                   nl_recvmsg_msg_cb_t func, void *arg)
316 {
317         int i, err;
318
319         for (i = 0; i <= NL_CB_TYPE_MAX; i++) {
320                 err = nl_cb_set(cb, i, kind, func, arg);
321                 if (err < 0)
322                         return err;
323         }
324
325         return 0;
326 }
327
328 /**
329  * Set up an error callback
330  * @arg cb              callback set
331  * @arg kind            kind of callback
332  * @arg func            callback function
333  * @arg arg             argument to be passed to callback function
334  */
335 int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind,
336               nl_recvmsg_err_cb_t func, void *arg)
337 {
338         if (kind < 0 || kind > NL_CB_KIND_MAX)
339                 return -NLE_RANGE;
340
341         if (kind == NL_CB_CUSTOM) {
342                 cb->cb_err = func;
343                 cb->cb_err_arg = arg;
344         } else {
345                 cb->cb_err = cb_err_def[kind];
346                 cb->cb_err_arg = arg;
347         }
348
349         return 0;
350 }
351
352 /** @} */
353
354 /**
355  * @name Overwriting
356  * @{
357  */
358
359 /**
360  * Overwrite internal calls to nl_recvmsgs()
361  * @arg cb              callback set
362  * @arg func            replacement callback for nl_recvmsgs()
363  */
364 void nl_cb_overwrite_recvmsgs(struct nl_cb *cb,
365                               int (*func)(struct nl_sock *, struct nl_cb *))
366 {
367         cb->cb_recvmsgs_ow = func;
368 }
369
370 /**
371  * Overwrite internal calls to nl_recv()
372  * @arg cb              callback set
373  * @arg func            replacement callback for nl_recv()
374  */
375 void nl_cb_overwrite_recv(struct nl_cb *cb,
376                           int (*func)(struct nl_sock *, struct sockaddr_nl *,
377                                       unsigned char **, struct ucred **))
378 {
379         cb->cb_recv_ow = func;
380 }
381
382 /**
383  * Overwrite internal calls to nl_send()
384  * @arg cb              callback set
385  * @arg func            replacement callback for nl_send()
386  */
387 void nl_cb_overwrite_send(struct nl_cb *cb,
388                           int (*func)(struct nl_sock *, struct nl_msg *))
389 {
390         cb->cb_send_ow = func;
391 }
392
393 /** @} */
394
395 /** @} */