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-2008 Thomas Graf <tgraf@suug.ch>
14 * @defgroup cb Callbacks/Customization
17 * @par 1) Setting up a callback set
19 * // Allocate a callback set and initialize it to the verbose default set
20 * struct nl_cb *cb = nl_cb_alloc(NL_CB_VERBOSE);
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);
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);
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>
39 static void print_header_content(FILE *ofd, struct nlmsghdr *n)
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);
50 static int nl_valid_handler_verbose(struct nl_msg *msg, void *arg)
52 FILE *ofd = arg ? arg : stdout;
54 fprintf(ofd, "-- Warning: unhandled valid message: ");
55 print_header_content(ofd, nlmsg_hdr(msg));
61 static int nl_invalid_handler_verbose(struct nl_msg *msg, void *arg)
63 FILE *ofd = arg ? arg : stderr;
65 fprintf(ofd, "-- Error: Invalid message: ");
66 print_header_content(ofd, nlmsg_hdr(msg));
72 static int nl_overrun_handler_verbose(struct nl_msg *msg, void *arg)
74 FILE *ofd = arg ? arg : stderr;
76 fprintf(ofd, "-- Error: Netlink Overrun: ");
77 print_header_content(ofd, nlmsg_hdr(msg));
83 static int nl_error_handler_verbose(struct sockaddr_nl *who,
84 struct nlmsgerr *e, void *arg)
86 FILE *ofd = arg ? arg : stderr;
88 fprintf(ofd, "-- Error received: %s\n-- Original message: ",
90 print_header_content(ofd, &e->msg);
93 return -nl_syserr2nlerr(e->error);
96 static int nl_valid_handler_debug(struct nl_msg *msg, void *arg)
98 FILE *ofd = arg ? arg : stderr;
100 fprintf(ofd, "-- Debug: Unhandled Valid message: ");
101 print_header_content(ofd, nlmsg_hdr(msg));
107 static int nl_finish_handler_debug(struct nl_msg *msg, void *arg)
109 FILE *ofd = arg ? arg : stderr;
111 fprintf(ofd, "-- Debug: End of multipart message block: ");
112 print_header_content(ofd, nlmsg_hdr(msg));
118 static int nl_msg_in_handler_debug(struct nl_msg *msg, void *arg)
120 FILE *ofd = arg ? arg : stderr;
122 fprintf(ofd, "-- Debug: Received Message:\n");
123 nl_msg_dump(msg, ofd);
128 static int nl_msg_out_handler_debug(struct nl_msg *msg, void *arg)
130 FILE *ofd = arg ? arg : stderr;
132 fprintf(ofd, "-- Debug: Sent Message:\n");
133 nl_msg_dump(msg, ofd);
138 static int nl_skipped_handler_debug(struct nl_msg *msg, void *arg)
140 FILE *ofd = arg ? arg : stderr;
142 fprintf(ofd, "-- Debug: Skipped message: ");
143 print_header_content(ofd, nlmsg_hdr(msg));
149 static int nl_ack_handler_debug(struct nl_msg *msg, void *arg)
151 FILE *ofd = arg ? arg : stderr;
153 fprintf(ofd, "-- Debug: ACK: ");
154 print_header_content(ofd, nlmsg_hdr(msg));
160 static nl_recvmsg_msg_cb_t cb_def[NL_CB_TYPE_MAX+1][NL_CB_KIND_MAX+1] = {
162 [NL_CB_VERBOSE] = nl_valid_handler_verbose,
163 [NL_CB_DEBUG] = nl_valid_handler_debug,
166 [NL_CB_DEBUG] = nl_finish_handler_debug,
169 [NL_CB_VERBOSE] = nl_invalid_handler_verbose,
170 [NL_CB_DEBUG] = nl_invalid_handler_verbose,
173 [NL_CB_DEBUG] = nl_msg_in_handler_debug,
176 [NL_CB_DEBUG] = nl_msg_out_handler_debug,
179 [NL_CB_VERBOSE] = nl_overrun_handler_verbose,
180 [NL_CB_DEBUG] = nl_overrun_handler_verbose,
183 [NL_CB_DEBUG] = nl_skipped_handler_debug,
186 [NL_CB_DEBUG] = nl_ack_handler_debug,
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,
196 * @name Callback Handle Management
201 * Allocate a new callback handle
202 * @arg kind callback kind to be used for initialization
203 * @return Newly allocated callback handle or NULL
205 struct nl_cb *nl_cb_alloc(enum nl_cb_kind kind)
210 if (kind < 0 || kind > NL_CB_KIND_MAX)
213 cb = calloc(1, sizeof(*cb));
219 for (i = 0; i <= NL_CB_TYPE_MAX; i++)
220 nl_cb_set(cb, i, kind, NULL, NULL);
222 nl_cb_err(cb, kind, NULL, NULL);
228 * Clone an existing callback handle
229 * @arg orig original callback handle
230 * @return Newly allocated callback handle being a duplicate of
233 struct nl_cb *nl_cb_clone(struct nl_cb *orig)
237 cb = nl_cb_alloc(NL_CB_DEFAULT);
241 memcpy(cb, orig, sizeof(*orig));
247 struct nl_cb *nl_cb_get(struct nl_cb *cb)
254 void nl_cb_put(struct nl_cb *cb)
261 if (cb->cb_refcnt < 0)
264 if (cb->cb_refcnt <= 0)
271 * @name Callback Setup
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
283 * @return 0 on success or a negative error code
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)
288 if (type < 0 || type > NL_CB_TYPE_MAX)
291 if (kind < 0 || kind > NL_CB_KIND_MAX)
294 if (kind == NL_CB_CUSTOM) {
295 cb->cb_set[type] = func;
296 cb->cb_args[type] = arg;
298 cb->cb_set[type] = cb_def[type][kind];
299 cb->cb_args[type] = arg;
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
312 * @return 0 on success or a negative error code
314 int nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind,
315 nl_recvmsg_msg_cb_t func, void *arg)
319 for (i = 0; i <= NL_CB_TYPE_MAX; i++) {
320 err = nl_cb_set(cb, i, kind, func, arg);
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
335 int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind,
336 nl_recvmsg_err_cb_t func, void *arg)
338 if (kind < 0 || kind > NL_CB_KIND_MAX)
341 if (kind == NL_CB_CUSTOM) {
343 cb->cb_err_arg = arg;
345 cb->cb_err = cb_err_def[kind];
346 cb->cb_err_arg = arg;
360 * Overwrite internal calls to nl_recvmsgs()
361 * @arg cb callback set
362 * @arg func replacement callback for nl_recvmsgs()
364 void nl_cb_overwrite_recvmsgs(struct nl_cb *cb,
365 int (*func)(struct nl_sock *, struct nl_cb *))
367 cb->cb_recvmsgs_ow = func;
371 * Overwrite internal calls to nl_recv()
372 * @arg cb callback set
373 * @arg func replacement callback for nl_recv()
375 void nl_cb_overwrite_recv(struct nl_cb *cb,
376 int (*func)(struct nl_sock *, struct sockaddr_nl *,
377 unsigned char **, struct ucred **))
379 cb->cb_recv_ow = func;
383 * Overwrite internal calls to nl_send()
384 * @arg cb callback set
385 * @arg func replacement callback for nl_send()
387 void nl_cb_overwrite_send(struct nl_cb *cb,
388 int (*func)(struct nl_sock *, struct nl_msg *))
390 cb->cb_send_ow = func;