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
16 * Customization via callbacks.
20 #include <netlink-local.h>
21 #include <netlink/netlink.h>
22 #include <netlink/utils.h>
23 #include <netlink/msg.h>
24 #include <netlink/handlers.h>
26 static void print_header_content(FILE *ofd, struct nlmsghdr *n)
31 fprintf(ofd, "type=%s length=%u flags=<%s> sequence-nr=%u pid=%u",
32 nl_nlmsgtype2str(n->nlmsg_type, type, sizeof(type)),
33 n->nlmsg_len, nl_nlmsg_flags2str(n->nlmsg_flags, flags,
34 sizeof(flags)), n->nlmsg_seq, n->nlmsg_pid);
37 static inline void dump_hex(FILE *ofd, char *start, int len)
45 for (i = 0, a = 0, c = 0; i < len; i++) {
46 int v = *(uint8_t *) (start + i);
48 fprintf(ofd, "%02x ", v);
49 ascii[a++] = isprint(v) ? v : '.';
52 fprintf(ofd, "%s\n", ascii);
56 memset(ascii, 0, sizeof(ascii));
62 for (i = 0; i < (limit - c); i++)
64 fprintf(ofd, "%s\n", ascii);
68 static void print_hdr(FILE *ofd, struct nl_msg *msg)
70 struct nlmsghdr *nlh = nlmsg_hdr(msg);
71 struct nl_cache_ops *ops;
74 fprintf(ofd, " .nlmsg_len = %d\n", nlh->nlmsg_len);
76 ops = nl_cache_mngt_associate(nlmsg_get_proto(msg), nlh->nlmsg_type);
78 fprintf(ofd, " .nlmsg_type = %d <%s>\n", nlh->nlmsg_type,
79 ops ? nl_cache_mngt_type2name(ops, nlh->nlmsg_type,
81 : nl_nlmsgtype2str(nlh->nlmsg_type, buf, sizeof(buf)));
82 fprintf(ofd, " .nlmsg_flags = %d <%s>\n", nlh->nlmsg_flags,
83 nl_nlmsg_flags2str(nlh->nlmsg_flags, buf, sizeof(buf)));
84 fprintf(ofd, " .nlmsg_seq = %d\n", nlh->nlmsg_seq);
85 fprintf(ofd, " .nlmsg_pid = %d\n", nlh->nlmsg_pid);
89 static void raw_dump_msg(FILE *ofd, struct nl_msg *msg)
91 struct nlmsghdr *hdr = nlmsg_hdr(msg);
94 "-------------------------- BEGIN NETLINK MESSAGE "
95 "---------------------------\n");
97 fprintf(ofd, " [HEADER] %Zu octets\n", sizeof(struct nlmsghdr));
100 if (hdr->nlmsg_type == NLMSG_ERROR &&
101 hdr->nlmsg_len >= nlmsg_msg_size(sizeof(struct nlmsgerr))) {
102 struct nl_msg *errmsg;
103 struct nlmsgerr *err = nlmsg_data(hdr);
105 fprintf(ofd, " [ERRORMSG] %Zu octets\n", sizeof(*err));
106 fprintf(ofd, " .error = %d \"%s\"\n", err->error,
107 strerror(-err->error));
108 fprintf(ofd, " [ORIGINAL MESSAGE] %Zu octets\n", sizeof(*hdr));
110 errmsg = nlmsg_build(&err->msg);
111 print_hdr(ofd, errmsg);
113 } else if (nlmsg_len(hdr) > 0) {
114 struct nl_cache_ops *ops;
115 int payloadlen = nlmsg_len(hdr);
118 ops = nl_cache_mngt_associate(nlmsg_get_proto(msg),
121 attrlen = nlmsg_attrlen(hdr, ops->co_hdrsize);
122 payloadlen -= attrlen;
125 fprintf(ofd, " [PAYLOAD] %d octets\n", payloadlen);
126 dump_hex(ofd, nlmsg_data(hdr), payloadlen);
132 nlmsg_for_each_attr(nla, hdr, ops->co_hdrsize, rem) {
133 int alen = nla_len(nla);
135 fprintf(ofd, " [ATTR %02d] %d octets\n",
136 nla->nla_type, alen);
137 dump_hex(ofd, nla_data(nla), alen);
139 padlen = nla_padlen(alen);
141 fprintf(ofd, " [PADDING] %d octets\n",
143 dump_hex(ofd, nla_data(nla) + alen,
151 "--------------------------- END NETLINK MESSAGE "
152 "---------------------------\n");
155 static int nl_valid_handler_default(struct nl_msg *msg, void *arg)
160 static int nl_finish_handler_default(struct nl_msg *msg, void *arg)
165 static int nl_invalid_handler_default(struct nl_msg *msg, void *arg)
170 static int nl_msg_in_handler_default(struct nl_msg *msg, void *arg)
175 static int nl_msg_out_handler_default(struct nl_msg *msg, void *arg)
180 static int nl_overrun_handler_default(struct nl_msg *msg, void *arg)
185 static int nl_skipped_handler_default(struct nl_msg *msg, void *arg)
190 static int nl_ack_handler_default(struct nl_msg *msg, void *arg)
195 static int nl_error_handler_default(struct sockaddr_nl *who,
196 struct nlmsgerr *e, void *arg)
201 static int nl_valid_handler_verbose(struct nl_msg *msg, void *arg)
203 FILE *ofd = arg ? arg : stdout;
205 fprintf(ofd, "-- Warning: unhandled valid message: ");
206 print_header_content(ofd, nlmsg_hdr(msg));
212 static int nl_finish_handler_verbose(struct nl_msg *msg, void *arg)
217 static int nl_msg_in_handler_verbose(struct nl_msg *msg, void *arg)
222 static int nl_invalid_handler_verbose(struct nl_msg *msg, void *arg)
224 FILE *ofd = arg ? arg : stderr;
226 fprintf(ofd, "-- Error: Invalid message: ");
227 print_header_content(ofd, nlmsg_hdr(msg));
233 static int nl_msg_out_handler_verbose(struct nl_msg *msg, void *arg)
238 static int nl_overrun_handler_verbose(struct nl_msg *msg, void *arg)
240 FILE *ofd = arg ? arg : stderr;
242 fprintf(ofd, "-- Error: Netlink Overrun: ");
243 print_header_content(ofd, nlmsg_hdr(msg));
249 static int nl_ack_handler_verbose(struct nl_msg *msg, void *arg)
254 static int nl_skipped_handler_verbose(struct nl_msg *msg, void *arg)
259 static int nl_error_handler_verbose(struct sockaddr_nl *who,
260 struct nlmsgerr *e, void *arg)
262 FILE *ofd = arg ? arg : stderr;
264 fprintf(ofd, "-- Error received: %s\n-- Original message: ",
265 strerror(-e->error));
266 print_header_content(ofd, &e->msg);
272 static int nl_valid_handler_debug(struct nl_msg *msg, void *arg)
274 FILE *ofd = arg ? arg : stderr;
276 fprintf(ofd, "-- Debug: Valid message: ");
277 print_header_content(ofd, nlmsg_hdr(msg));
283 static int nl_finish_handler_debug(struct nl_msg *msg, void *arg)
285 FILE *ofd = arg ? arg : stderr;
287 fprintf(ofd, "-- Debug: End of multipart message block: ");
288 print_header_content(ofd, nlmsg_hdr(msg));
294 static int nl_invalid_handler_debug(struct nl_msg *msg, void *arg)
296 return nl_invalid_handler_verbose(msg, arg);
299 static int nl_msg_in_handler_debug(struct nl_msg *msg, void *arg)
301 FILE *ofd = arg ? arg : stderr;
303 fprintf(ofd, "-- Debug: Received Message:\n");
304 raw_dump_msg(ofd, msg);
309 static int nl_msg_out_handler_debug(struct nl_msg *msg, void *arg)
311 FILE *ofd = arg ? arg : stderr;
313 fprintf(ofd, "-- Debug: Sent Message:\n");
314 raw_dump_msg(ofd, msg);
319 static int nl_overrun_handler_debug(struct nl_msg *msg, void *arg)
321 return nl_overrun_handler_verbose(msg, arg);
324 static int nl_skipped_handler_debug(struct nl_msg *msg, void *arg)
326 FILE *ofd = arg ? arg : stderr;
328 fprintf(ofd, "-- Debug: Skipped message: ");
329 print_header_content(ofd, nlmsg_hdr(msg));
335 static int nl_ack_handler_debug(struct nl_msg *msg, void *arg)
337 FILE *ofd = arg ? arg : stderr;
339 fprintf(ofd, "-- Debug: ACK: ");
340 print_header_content(ofd, nlmsg_hdr(msg));
346 static int nl_error_handler_debug(struct sockaddr_nl *who,
347 struct nlmsgerr *e, void *arg)
349 return nl_error_handler_verbose(who, e, arg);
352 static nl_recvmsg_msg_cb_t cb_def[NL_CB_TYPE_MAX+1][NL_CB_KIND_MAX+1] = {
354 [NL_CB_DEFAULT] = nl_valid_handler_default,
355 [NL_CB_VERBOSE] = nl_valid_handler_verbose,
356 [NL_CB_DEBUG] = nl_valid_handler_debug,
359 [NL_CB_DEFAULT] = nl_finish_handler_default,
360 [NL_CB_VERBOSE] = nl_finish_handler_verbose,
361 [NL_CB_DEBUG] = nl_finish_handler_debug,
364 [NL_CB_DEFAULT] = nl_invalid_handler_default,
365 [NL_CB_VERBOSE] = nl_invalid_handler_verbose,
366 [NL_CB_DEBUG] = nl_invalid_handler_debug,
369 [NL_CB_DEFAULT] = nl_msg_in_handler_default,
370 [NL_CB_VERBOSE] = nl_msg_in_handler_verbose,
371 [NL_CB_DEBUG] = nl_msg_in_handler_debug,
374 [NL_CB_DEFAULT] = nl_msg_out_handler_default,
375 [NL_CB_VERBOSE] = nl_msg_out_handler_verbose,
376 [NL_CB_DEBUG] = nl_msg_out_handler_debug,
379 [NL_CB_DEFAULT] = nl_overrun_handler_default,
380 [NL_CB_VERBOSE] = nl_overrun_handler_verbose,
381 [NL_CB_DEBUG] = nl_overrun_handler_debug,
384 [NL_CB_DEFAULT] = nl_skipped_handler_default,
385 [NL_CB_VERBOSE] = nl_skipped_handler_verbose,
386 [NL_CB_DEBUG] = nl_skipped_handler_debug,
389 [NL_CB_DEFAULT] = nl_ack_handler_default,
390 [NL_CB_VERBOSE] = nl_ack_handler_verbose,
391 [NL_CB_DEBUG] = nl_ack_handler_debug,
395 static nl_recvmsg_err_cb_t cb_err_def[NL_CB_KIND_MAX+1] = {
396 [NL_CB_DEFAULT] = nl_error_handler_default,
397 [NL_CB_VERBOSE] = nl_error_handler_verbose,
398 [NL_CB_DEBUG] = nl_error_handler_debug,
402 * @name Callback Handle Management
407 * Allocate a new callback handle
408 * @arg kind callback kind to be used for initialization
409 * @return Newly allocated callback handle or NULL
411 struct nl_cb *nl_cb_new(enum nl_cb_kind kind)
416 if (kind < 0 || kind > NL_CB_KIND_MAX)
419 cb = calloc(1, sizeof(*cb));
425 for (i = 0; i <= NL_CB_TYPE_MAX; i++)
426 nl_cb_set(cb, i, kind, NULL, NULL);
428 nl_cb_err(cb, kind, NULL, NULL);
434 * Destroy a callback handle
435 * @arg cb callback handle
437 void nl_cb_destroy(struct nl_cb *cb)
443 * Clone an existing callback handle
444 * @arg orig original callback handle
445 * @return Newly allocated callback handle being a duplicate of
448 struct nl_cb *nl_cb_clone(struct nl_cb *orig)
452 cb = nl_cb_new(NL_CB_DEFAULT);
456 memcpy(cb, orig, sizeof(*orig));
464 * @name Callback Setup
470 * @arg cb callback configuration
471 * @arg type which type callback to set
472 * @arg kind kind of callback
473 * @arg func callback function
474 * @arg arg argument to be passwd to callback function
476 * @return 0 on success or a negative error code
478 int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind,
479 nl_recvmsg_msg_cb_t func, void *arg)
481 if (type < 0 || type > NL_CB_TYPE_MAX)
482 return nl_error(ERANGE, "Callback type out of range");
484 if (kind < 0 || kind > NL_CB_KIND_MAX)
485 return nl_error(ERANGE, "Callback kind out of range");
487 if (kind == NL_CB_CUSTOM) {
488 cb->cb_set[type] = func;
489 cb->cb_args[type] = arg;
491 cb->cb_set[type] = cb_def[type][kind];
492 cb->cb_args[type] = arg;
499 * Set up a all callbacks
500 * @arg cb callback configuration
501 * @arg kind kind of callback
502 * @arg func callback function
503 * @arg arg argument to be passwd to callback function
505 * @return 0 on success or a negative error code
507 int nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind,
508 nl_recvmsg_msg_cb_t func, void *arg)
512 for (i = 0; i <= NL_CB_TYPE_MAX; i++) {
513 err = nl_cb_set(cb, i, kind, func, arg);
522 * Set up an error callback
523 * @arg cb callback configuration
524 * @arg kind kind of callback
525 * @arg func callback function
526 * @arg arg argument to be passed to callback function
528 int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind,
529 nl_recvmsg_err_cb_t func, void *arg)
531 if (kind < 0 || kind > NL_CB_KIND_MAX)
532 return nl_error(ERANGE, "Callback kind out of range");
534 if (kind == NL_CB_CUSTOM) {
536 cb->cb_err_arg = arg;
538 cb->cb_err = cb_err_def[kind];
539 cb->cb_err_arg = arg;
546 * Overwrite internal calls to nl_recvmsgs()
547 * @arg cb callback configuration
548 * @arg func replacement callback for nl_recvmsgs()
550 void nl_cb_overwrite_recvmsgs(struct nl_cb *cb,
551 int (*func)(struct nl_handle *, struct nl_cb *))
553 cb->cb_recvmsgs_ow = func;
557 * Overwrite internal calls to nl_recv()
558 * @arg cb callback configuration
559 * @arg func replacement callback for nl_recv()
561 void nl_cb_overwrite_recv(struct nl_cb *cb,
562 int (*func)(struct nl_handle *, struct sockaddr_nl *,
563 unsigned char **, struct ucred **))
565 cb->cb_recv_ow = func;
569 * Overwrite internal calls to nl_send()
570 * @arg cb callback configuration
571 * @arg func replacement callback for nl_send()
573 void nl_cb_overwrite_send(struct nl_cb *cb,
574 int (*func)(struct nl_handle *, struct nl_msg *))
576 cb->cb_send_ow = func;