2 * lib/handlers.c default netlink message handlers
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
9 * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
14 * @defgroup cb Callbacks/Customization
17 * Callbacks and overwriting capabilities are provided to take influence
18 * in various control flows inside the library. All callbacks are packed
19 * together in struct nl_cb which is then attached to a netlink socket or
20 * passed on to the respective functions directly.
22 * Callbacks can control the flow of the underlying layer by returning
23 * the appropriate error codes:
25 * Action ID | Description
26 * -----------------+-------------------------------------------------------
27 * NL_OK | Proceed with whatever comes next.
28 * NL_SKIP | Skip message currently being processed and continue
29 * | with next message.
30 * NL_STOP | Stop parsing and discard all remaining messages in
31 * | this set of messages.
34 * All callbacks are optional and a default action is performed if no
35 * application specific implementation is provided:
38 * Callback ID | Default Return Value
39 * ------------------+----------------------
41 * NL_CB_FINISH | NL_STOP
42 * NL_CB_OVERRUN | NL_STOP
43 * NL_CB_SKIPPED | NL_SKIP
45 * NL_CB_MSG_IN | NL_OK
46 * NL_CB_MSG_OUT | NL_OK
47 * NL_CB_INVALID | NL_STOP
48 * NL_CB_SEQ_CHECK | NL_OK
49 * NL_CB_SEND_ACK | NL_OK
51 * Error Callback | NL_STOP
54 * In order to simplify typical usages of the library, different sets of
55 * default callback implementations exist:
57 * NL_CB_DEFAULT: No additional actions
58 * NL_CB_VERBOSE: Automatically print warning and error messages to a file
59 * descriptor as appropriate. This is useful for CLI based
61 * NL_CB_DEBUG: Print informal debugging information for each message
62 * received. This will result in every message beint sent or
63 * received to be printed to the screen in a decoded,
64 * human-readable format.
67 * @par 1) Setting up a callback set
69 * // Allocate a callback set and initialize it to the verbose default set
70 * struct nl_cb *cb = nl_cb_alloc(NL_CB_VERBOSE);
72 * // Modify the set to call my_func() for all valid messages
73 * nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL);
75 * // Set the error message handler to the verbose default implementation
76 * // and direct it to print all errors to the given file descriptor.
77 * FILE *file = fopen(...);
78 * nl_cb_err(cb, NL_CB_VERBOSE, NULL, file);
83 #include <netlink-local.h>
84 #include <netlink/netlink.h>
85 #include <netlink/utils.h>
86 #include <netlink/msg.h>
87 #include <netlink/handlers.h>
89 static void print_header_content(FILE *ofd, struct nlmsghdr *n)
94 fprintf(ofd, "type=%s length=%u flags=<%s> sequence-nr=%u pid=%u",
95 nl_nlmsgtype2str(n->nlmsg_type, type, sizeof(type)),
96 n->nlmsg_len, nl_nlmsg_flags2str(n->nlmsg_flags, flags,
97 sizeof(flags)), n->nlmsg_seq, n->nlmsg_pid);
100 static int nl_valid_handler_verbose(struct nl_msg *msg, void *arg)
102 FILE *ofd = arg ? arg : stdout;
104 fprintf(ofd, "-- Warning: unhandled valid message: ");
105 print_header_content(ofd, nlmsg_hdr(msg));
111 static int nl_invalid_handler_verbose(struct nl_msg *msg, void *arg)
113 FILE *ofd = arg ? arg : stderr;
115 fprintf(ofd, "-- Error: Invalid message: ");
116 print_header_content(ofd, nlmsg_hdr(msg));
122 static int nl_overrun_handler_verbose(struct nl_msg *msg, void *arg)
124 FILE *ofd = arg ? arg : stderr;
126 fprintf(ofd, "-- Error: Netlink Overrun: ");
127 print_header_content(ofd, nlmsg_hdr(msg));
133 static int nl_error_handler_verbose(struct sockaddr_nl *who,
134 struct nlmsgerr *e, void *arg)
136 FILE *ofd = arg ? arg : stderr;
138 fprintf(ofd, "-- Error received: %s\n-- Original message: ",
139 strerror(-e->error));
140 print_header_content(ofd, &e->msg);
146 static int nl_valid_handler_debug(struct nl_msg *msg, void *arg)
148 FILE *ofd = arg ? arg : stderr;
150 fprintf(ofd, "-- Debug: Unhandled Valid message: ");
151 print_header_content(ofd, nlmsg_hdr(msg));
157 static int nl_finish_handler_debug(struct nl_msg *msg, void *arg)
159 FILE *ofd = arg ? arg : stderr;
161 fprintf(ofd, "-- Debug: End of multipart message block: ");
162 print_header_content(ofd, nlmsg_hdr(msg));
168 static int nl_msg_in_handler_debug(struct nl_msg *msg, void *arg)
170 FILE *ofd = arg ? arg : stderr;
172 fprintf(ofd, "-- Debug: Received Message:\n");
173 nl_msg_dump(msg, ofd);
178 static int nl_msg_out_handler_debug(struct nl_msg *msg, void *arg)
180 FILE *ofd = arg ? arg : stderr;
182 fprintf(ofd, "-- Debug: Sent Message:\n");
183 nl_msg_dump(msg, ofd);
188 static int nl_skipped_handler_debug(struct nl_msg *msg, void *arg)
190 FILE *ofd = arg ? arg : stderr;
192 fprintf(ofd, "-- Debug: Skipped message: ");
193 print_header_content(ofd, nlmsg_hdr(msg));
199 static int nl_ack_handler_debug(struct nl_msg *msg, void *arg)
201 FILE *ofd = arg ? arg : stderr;
203 fprintf(ofd, "-- Debug: ACK: ");
204 print_header_content(ofd, nlmsg_hdr(msg));
210 static nl_recvmsg_msg_cb_t cb_def[NL_CB_TYPE_MAX+1][NL_CB_KIND_MAX+1] = {
212 [NL_CB_VERBOSE] = nl_valid_handler_verbose,
213 [NL_CB_DEBUG] = nl_valid_handler_debug,
216 [NL_CB_DEBUG] = nl_finish_handler_debug,
219 [NL_CB_VERBOSE] = nl_invalid_handler_verbose,
220 [NL_CB_DEBUG] = nl_invalid_handler_verbose,
223 [NL_CB_DEBUG] = nl_msg_in_handler_debug,
226 [NL_CB_DEBUG] = nl_msg_out_handler_debug,
229 [NL_CB_VERBOSE] = nl_overrun_handler_verbose,
230 [NL_CB_DEBUG] = nl_overrun_handler_verbose,
233 [NL_CB_DEBUG] = nl_skipped_handler_debug,
236 [NL_CB_DEBUG] = nl_ack_handler_debug,
240 static nl_recvmsg_err_cb_t cb_err_def[NL_CB_KIND_MAX+1] = {
241 [NL_CB_VERBOSE] = nl_error_handler_verbose,
242 [NL_CB_DEBUG] = nl_error_handler_verbose,
246 * @name Callback Handle Management
251 * Allocate a new callback handle
252 * @arg kind callback kind to be used for initialization
253 * @return Newly allocated callback handle or NULL
255 struct nl_cb *nl_cb_alloc(enum nl_cb_kind kind)
260 if (kind < 0 || kind > NL_CB_KIND_MAX)
263 cb = calloc(1, sizeof(*cb));
271 for (i = 0; i <= NL_CB_TYPE_MAX; i++)
272 nl_cb_set(cb, i, kind, NULL, NULL);
274 nl_cb_err(cb, kind, NULL, NULL);
280 * Clone an existing callback handle
281 * @arg orig original callback handle
282 * @return Newly allocated callback handle being a duplicate of
285 struct nl_cb *nl_cb_clone(struct nl_cb *orig)
289 cb = nl_cb_alloc(NL_CB_DEFAULT);
293 memcpy(cb, orig, sizeof(*orig));
299 struct nl_cb *nl_cb_get(struct nl_cb *cb)
306 void nl_cb_put(struct nl_cb *cb)
313 if (cb->cb_refcnt < 0)
316 if (cb->cb_refcnt <= 0)
323 * @name Callback Setup
329 * @arg cb callback set
330 * @arg type callback to modify
331 * @arg kind kind of implementation
332 * @arg func callback function (NL_CB_CUSTOM)
333 * @arg arg argument passed to callback
335 * @return 0 on success or a negative error code
337 int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind,
338 nl_recvmsg_msg_cb_t func, void *arg)
340 if (type < 0 || type > NL_CB_TYPE_MAX)
341 return nl_error(ERANGE, "Callback type out of range");
343 if (kind < 0 || kind > NL_CB_KIND_MAX)
344 return nl_error(ERANGE, "Callback kind out of range");
346 if (kind == NL_CB_CUSTOM) {
347 cb->cb_set[type] = func;
348 cb->cb_args[type] = arg;
350 cb->cb_set[type] = cb_def[type][kind];
351 cb->cb_args[type] = arg;
358 * Set up a all callbacks
359 * @arg cb callback set
360 * @arg kind kind of callback
361 * @arg func callback function
362 * @arg arg argument to be passwd to callback function
364 * @return 0 on success or a negative error code
366 int nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind,
367 nl_recvmsg_msg_cb_t func, void *arg)
371 for (i = 0; i <= NL_CB_TYPE_MAX; i++) {
372 err = nl_cb_set(cb, i, kind, func, arg);
381 * Set up an error callback
382 * @arg cb callback set
383 * @arg kind kind of callback
384 * @arg func callback function
385 * @arg arg argument to be passed to callback function
387 int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind,
388 nl_recvmsg_err_cb_t func, void *arg)
390 if (kind < 0 || kind > NL_CB_KIND_MAX)
391 return nl_error(ERANGE, "Callback kind out of range");
393 if (kind == NL_CB_CUSTOM) {
395 cb->cb_err_arg = arg;
397 cb->cb_err = cb_err_def[kind];
398 cb->cb_err_arg = arg;
412 * Overwrite internal calls to nl_recvmsgs()
413 * @arg cb callback set
414 * @arg func replacement callback for nl_recvmsgs()
416 void nl_cb_overwrite_recvmsgs(struct nl_cb *cb,
417 int (*func)(struct nl_handle *, struct nl_cb *))
419 cb->cb_recvmsgs_ow = func;
423 * Overwrite internal calls to nl_recv()
424 * @arg cb callback set
425 * @arg func replacement callback for nl_recv()
427 void nl_cb_overwrite_recv(struct nl_cb *cb,
428 int (*func)(struct nl_handle *, struct sockaddr_nl *,
429 unsigned char **, struct ucred **))
431 cb->cb_recv_ow = func;
435 * Overwrite internal calls to nl_send()
436 * @arg cb callback set
437 * @arg func replacement callback for nl_send()
439 void nl_cb_overwrite_send(struct nl_cb *cb,
440 int (*func)(struct nl_handle *, struct nl_msg *))
442 cb->cb_send_ow = func;