144d362409d5469aed47d19e7908d19bd194493aThomas Graf/*
244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/handlers.c	default netlink message handlers
344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
444d362409d5469aed47d19e7908d19bd194493aThomas Graf *	This library is free software; you can redistribute it and/or
544d362409d5469aed47d19e7908d19bd194493aThomas Graf *	modify it under the terms of the GNU Lesser General Public
644d362409d5469aed47d19e7908d19bd194493aThomas Graf *	License as published by the Free Software Foundation version 2.1
744d362409d5469aed47d19e7908d19bd194493aThomas Graf *	of the License.
844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
98a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1144d362409d5469aed47d19e7908d19bd194493aThomas Graf
1244d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
136782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf * @ingroup core
1444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup cb Callbacks/Customization
1544d362409d5469aed47d19e7908d19bd194493aThomas Graf *
164fd5f7cb6627a22bd9f228b4259d5106ae39d535Thomas Graf * @details
1744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par 1) Setting up a callback set
1844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code
1944d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Allocate a callback set and initialize it to the verbose default set
2044d362409d5469aed47d19e7908d19bd194493aThomas Graf * struct nl_cb *cb = nl_cb_alloc(NL_CB_VERBOSE);
2144d362409d5469aed47d19e7908d19bd194493aThomas Graf *
2244d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Modify the set to call my_func() for all valid messages
2344d362409d5469aed47d19e7908d19bd194493aThomas Graf * nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL);
2444d362409d5469aed47d19e7908d19bd194493aThomas Graf *
2544d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Set the error message handler to the verbose default implementation
2644d362409d5469aed47d19e7908d19bd194493aThomas Graf * // and direct it to print all errors to the given file descriptor.
2744d362409d5469aed47d19e7908d19bd194493aThomas Graf * FILE *file = fopen(...);
2844d362409d5469aed47d19e7908d19bd194493aThomas Graf * nl_cb_err(cb, NL_CB_VERBOSE, NULL, file);
2944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode
3044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
3144d362409d5469aed47d19e7908d19bd194493aThomas Graf */
3244d362409d5469aed47d19e7908d19bd194493aThomas Graf
3344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-local.h>
3444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h>
3544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h>
3644d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/msg.h>
3744d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/handlers.h>
3844d362409d5469aed47d19e7908d19bd194493aThomas Graf
3944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void print_header_content(FILE *ofd, struct nlmsghdr *n)
4044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
4144d362409d5469aed47d19e7908d19bd194493aThomas Graf	char flags[128];
4244d362409d5469aed47d19e7908d19bd194493aThomas Graf	char type[32];
4344d362409d5469aed47d19e7908d19bd194493aThomas Graf
4444d362409d5469aed47d19e7908d19bd194493aThomas Graf	fprintf(ofd, "type=%s length=%u flags=<%s> sequence-nr=%u pid=%u",
4544d362409d5469aed47d19e7908d19bd194493aThomas Graf		nl_nlmsgtype2str(n->nlmsg_type, type, sizeof(type)),
4644d362409d5469aed47d19e7908d19bd194493aThomas Graf		n->nlmsg_len, nl_nlmsg_flags2str(n->nlmsg_flags, flags,
4744d362409d5469aed47d19e7908d19bd194493aThomas Graf		sizeof(flags)), n->nlmsg_seq, n->nlmsg_pid);
4844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
4944d362409d5469aed47d19e7908d19bd194493aThomas Graf
5044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_valid_handler_verbose(struct nl_msg *msg, void *arg)
5144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
5244d362409d5469aed47d19e7908d19bd194493aThomas Graf	FILE *ofd = arg ? arg : stdout;
5344d362409d5469aed47d19e7908d19bd194493aThomas Graf
5444d362409d5469aed47d19e7908d19bd194493aThomas Graf	fprintf(ofd, "-- Warning: unhandled valid message: ");
5544d362409d5469aed47d19e7908d19bd194493aThomas Graf	print_header_content(ofd, nlmsg_hdr(msg));
5644d362409d5469aed47d19e7908d19bd194493aThomas Graf	fprintf(ofd, "\n");
5744d362409d5469aed47d19e7908d19bd194493aThomas Graf
5844d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NL_OK;
5944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
6044d362409d5469aed47d19e7908d19bd194493aThomas Graf
6144d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_invalid_handler_verbose(struct nl_msg *msg, void *arg)
6244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
6344d362409d5469aed47d19e7908d19bd194493aThomas Graf	FILE *ofd = arg ? arg : stderr;
6444d362409d5469aed47d19e7908d19bd194493aThomas Graf
6544d362409d5469aed47d19e7908d19bd194493aThomas Graf	fprintf(ofd, "-- Error: Invalid message: ");
6644d362409d5469aed47d19e7908d19bd194493aThomas Graf	print_header_content(ofd, nlmsg_hdr(msg));
6744d362409d5469aed47d19e7908d19bd194493aThomas Graf	fprintf(ofd, "\n");
6844d362409d5469aed47d19e7908d19bd194493aThomas Graf
6944d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NL_STOP;
7044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
7144d362409d5469aed47d19e7908d19bd194493aThomas Graf
7244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_overrun_handler_verbose(struct nl_msg *msg, void *arg)
7344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
7444d362409d5469aed47d19e7908d19bd194493aThomas Graf	FILE *ofd = arg ? arg : stderr;
7544d362409d5469aed47d19e7908d19bd194493aThomas Graf
7644d362409d5469aed47d19e7908d19bd194493aThomas Graf	fprintf(ofd, "-- Error: Netlink Overrun: ");
7744d362409d5469aed47d19e7908d19bd194493aThomas Graf	print_header_content(ofd, nlmsg_hdr(msg));
7844d362409d5469aed47d19e7908d19bd194493aThomas Graf	fprintf(ofd, "\n");
7944d362409d5469aed47d19e7908d19bd194493aThomas Graf
8044d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NL_STOP;
8144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
8244d362409d5469aed47d19e7908d19bd194493aThomas Graf
8344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_error_handler_verbose(struct sockaddr_nl *who,
8444d362409d5469aed47d19e7908d19bd194493aThomas Graf				    struct nlmsgerr *e, void *arg)
8544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
8644d362409d5469aed47d19e7908d19bd194493aThomas Graf	FILE *ofd = arg ? arg : stderr;
8744d362409d5469aed47d19e7908d19bd194493aThomas Graf
8844d362409d5469aed47d19e7908d19bd194493aThomas Graf	fprintf(ofd, "-- Error received: %s\n-- Original message: ",
8944d362409d5469aed47d19e7908d19bd194493aThomas Graf		strerror(-e->error));
9044d362409d5469aed47d19e7908d19bd194493aThomas Graf	print_header_content(ofd, &e->msg);
9144d362409d5469aed47d19e7908d19bd194493aThomas Graf	fprintf(ofd, "\n");
9244d362409d5469aed47d19e7908d19bd194493aThomas Graf
938a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	return -nl_syserr2nlerr(e->error);
9444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
9544d362409d5469aed47d19e7908d19bd194493aThomas Graf
9644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_valid_handler_debug(struct nl_msg *msg, void *arg)
9744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
9844d362409d5469aed47d19e7908d19bd194493aThomas Graf	FILE *ofd = arg ? arg : stderr;
9944d362409d5469aed47d19e7908d19bd194493aThomas Graf
10044d362409d5469aed47d19e7908d19bd194493aThomas Graf	fprintf(ofd, "-- Debug: Unhandled Valid message: ");
10144d362409d5469aed47d19e7908d19bd194493aThomas Graf	print_header_content(ofd, nlmsg_hdr(msg));
10244d362409d5469aed47d19e7908d19bd194493aThomas Graf	fprintf(ofd, "\n");
10344d362409d5469aed47d19e7908d19bd194493aThomas Graf
10444d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NL_OK;
10544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
10644d362409d5469aed47d19e7908d19bd194493aThomas Graf
10744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_finish_handler_debug(struct nl_msg *msg, void *arg)
10844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
10944d362409d5469aed47d19e7908d19bd194493aThomas Graf	FILE *ofd = arg ? arg : stderr;
11044d362409d5469aed47d19e7908d19bd194493aThomas Graf
11144d362409d5469aed47d19e7908d19bd194493aThomas Graf	fprintf(ofd, "-- Debug: End of multipart message block: ");
11244d362409d5469aed47d19e7908d19bd194493aThomas Graf	print_header_content(ofd, nlmsg_hdr(msg));
11344d362409d5469aed47d19e7908d19bd194493aThomas Graf	fprintf(ofd, "\n");
11444d362409d5469aed47d19e7908d19bd194493aThomas Graf
11544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NL_STOP;
11644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
11744d362409d5469aed47d19e7908d19bd194493aThomas Graf
11844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_msg_in_handler_debug(struct nl_msg *msg, void *arg)
11944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
12044d362409d5469aed47d19e7908d19bd194493aThomas Graf	FILE *ofd = arg ? arg : stderr;
12144d362409d5469aed47d19e7908d19bd194493aThomas Graf
12244d362409d5469aed47d19e7908d19bd194493aThomas Graf	fprintf(ofd, "-- Debug: Received Message:\n");
12344d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_msg_dump(msg, ofd);
12444d362409d5469aed47d19e7908d19bd194493aThomas Graf
12544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NL_OK;
12644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
12744d362409d5469aed47d19e7908d19bd194493aThomas Graf
12844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_msg_out_handler_debug(struct nl_msg *msg, void *arg)
12944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
13044d362409d5469aed47d19e7908d19bd194493aThomas Graf	FILE *ofd = arg ? arg : stderr;
13144d362409d5469aed47d19e7908d19bd194493aThomas Graf
13244d362409d5469aed47d19e7908d19bd194493aThomas Graf	fprintf(ofd, "-- Debug: Sent Message:\n");
13344d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_msg_dump(msg, ofd);
13444d362409d5469aed47d19e7908d19bd194493aThomas Graf
13544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NL_OK;
13644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
13744d362409d5469aed47d19e7908d19bd194493aThomas Graf
13844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_skipped_handler_debug(struct nl_msg *msg, void *arg)
13944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
14044d362409d5469aed47d19e7908d19bd194493aThomas Graf	FILE *ofd = arg ? arg : stderr;
14144d362409d5469aed47d19e7908d19bd194493aThomas Graf
14244d362409d5469aed47d19e7908d19bd194493aThomas Graf	fprintf(ofd, "-- Debug: Skipped message: ");
14344d362409d5469aed47d19e7908d19bd194493aThomas Graf	print_header_content(ofd, nlmsg_hdr(msg));
14444d362409d5469aed47d19e7908d19bd194493aThomas Graf	fprintf(ofd, "\n");
14544d362409d5469aed47d19e7908d19bd194493aThomas Graf
14644d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NL_SKIP;
14744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
14844d362409d5469aed47d19e7908d19bd194493aThomas Graf
14944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_ack_handler_debug(struct nl_msg *msg, void *arg)
15044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
15144d362409d5469aed47d19e7908d19bd194493aThomas Graf	FILE *ofd = arg ? arg : stderr;
15244d362409d5469aed47d19e7908d19bd194493aThomas Graf
15344d362409d5469aed47d19e7908d19bd194493aThomas Graf	fprintf(ofd, "-- Debug: ACK: ");
15444d362409d5469aed47d19e7908d19bd194493aThomas Graf	print_header_content(ofd, nlmsg_hdr(msg));
15544d362409d5469aed47d19e7908d19bd194493aThomas Graf	fprintf(ofd, "\n");
15644d362409d5469aed47d19e7908d19bd194493aThomas Graf
15744d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NL_STOP;
15844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
15944d362409d5469aed47d19e7908d19bd194493aThomas Graf
16044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic nl_recvmsg_msg_cb_t cb_def[NL_CB_TYPE_MAX+1][NL_CB_KIND_MAX+1] = {
16144d362409d5469aed47d19e7908d19bd194493aThomas Graf	[NL_CB_VALID] = {
16244d362409d5469aed47d19e7908d19bd194493aThomas Graf		[NL_CB_VERBOSE]	= nl_valid_handler_verbose,
16344d362409d5469aed47d19e7908d19bd194493aThomas Graf		[NL_CB_DEBUG]	= nl_valid_handler_debug,
16444d362409d5469aed47d19e7908d19bd194493aThomas Graf	},
16544d362409d5469aed47d19e7908d19bd194493aThomas Graf	[NL_CB_FINISH] = {
16644d362409d5469aed47d19e7908d19bd194493aThomas Graf		[NL_CB_DEBUG]	= nl_finish_handler_debug,
16744d362409d5469aed47d19e7908d19bd194493aThomas Graf	},
16844d362409d5469aed47d19e7908d19bd194493aThomas Graf	[NL_CB_INVALID] = {
16944d362409d5469aed47d19e7908d19bd194493aThomas Graf		[NL_CB_VERBOSE]	= nl_invalid_handler_verbose,
17044d362409d5469aed47d19e7908d19bd194493aThomas Graf		[NL_CB_DEBUG]	= nl_invalid_handler_verbose,
17144d362409d5469aed47d19e7908d19bd194493aThomas Graf	},
17244d362409d5469aed47d19e7908d19bd194493aThomas Graf	[NL_CB_MSG_IN] = {
17344d362409d5469aed47d19e7908d19bd194493aThomas Graf		[NL_CB_DEBUG]	= nl_msg_in_handler_debug,
17444d362409d5469aed47d19e7908d19bd194493aThomas Graf	},
17544d362409d5469aed47d19e7908d19bd194493aThomas Graf	[NL_CB_MSG_OUT] = {
17644d362409d5469aed47d19e7908d19bd194493aThomas Graf		[NL_CB_DEBUG]	= nl_msg_out_handler_debug,
17744d362409d5469aed47d19e7908d19bd194493aThomas Graf	},
17844d362409d5469aed47d19e7908d19bd194493aThomas Graf	[NL_CB_OVERRUN] = {
17944d362409d5469aed47d19e7908d19bd194493aThomas Graf		[NL_CB_VERBOSE]	= nl_overrun_handler_verbose,
18044d362409d5469aed47d19e7908d19bd194493aThomas Graf		[NL_CB_DEBUG]	= nl_overrun_handler_verbose,
18144d362409d5469aed47d19e7908d19bd194493aThomas Graf	},
18244d362409d5469aed47d19e7908d19bd194493aThomas Graf	[NL_CB_SKIPPED] = {
18344d362409d5469aed47d19e7908d19bd194493aThomas Graf		[NL_CB_DEBUG]	= nl_skipped_handler_debug,
18444d362409d5469aed47d19e7908d19bd194493aThomas Graf	},
18544d362409d5469aed47d19e7908d19bd194493aThomas Graf	[NL_CB_ACK] = {
18644d362409d5469aed47d19e7908d19bd194493aThomas Graf		[NL_CB_DEBUG]	= nl_ack_handler_debug,
18744d362409d5469aed47d19e7908d19bd194493aThomas Graf	},
18844d362409d5469aed47d19e7908d19bd194493aThomas Graf};
18944d362409d5469aed47d19e7908d19bd194493aThomas Graf
19044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic nl_recvmsg_err_cb_t cb_err_def[NL_CB_KIND_MAX+1] = {
19144d362409d5469aed47d19e7908d19bd194493aThomas Graf	[NL_CB_VERBOSE]	= nl_error_handler_verbose,
19244d362409d5469aed47d19e7908d19bd194493aThomas Graf	[NL_CB_DEBUG]	= nl_error_handler_verbose,
19344d362409d5469aed47d19e7908d19bd194493aThomas Graf};
19444d362409d5469aed47d19e7908d19bd194493aThomas Graf
19544d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
19644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Callback Handle Management
19744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
19844d362409d5469aed47d19e7908d19bd194493aThomas Graf */
19944d362409d5469aed47d19e7908d19bd194493aThomas Graf
20044d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
20144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Allocate a new callback handle
20244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg kind		callback kind to be used for initialization
20344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Newly allocated callback handle or NULL
20444d362409d5469aed47d19e7908d19bd194493aThomas Graf */
20544d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_cb *nl_cb_alloc(enum nl_cb_kind kind)
20644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
20744d362409d5469aed47d19e7908d19bd194493aThomas Graf	int i;
20844d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_cb *cb;
20944d362409d5469aed47d19e7908d19bd194493aThomas Graf
21044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (kind < 0 || kind > NL_CB_KIND_MAX)
21144d362409d5469aed47d19e7908d19bd194493aThomas Graf		return NULL;
21244d362409d5469aed47d19e7908d19bd194493aThomas Graf
21344d362409d5469aed47d19e7908d19bd194493aThomas Graf	cb = calloc(1, sizeof(*cb));
2148a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	if (!cb)
21544d362409d5469aed47d19e7908d19bd194493aThomas Graf		return NULL;
21644d362409d5469aed47d19e7908d19bd194493aThomas Graf
21744d362409d5469aed47d19e7908d19bd194493aThomas Graf	cb->cb_refcnt = 1;
21844d362409d5469aed47d19e7908d19bd194493aThomas Graf
21944d362409d5469aed47d19e7908d19bd194493aThomas Graf	for (i = 0; i <= NL_CB_TYPE_MAX; i++)
22044d362409d5469aed47d19e7908d19bd194493aThomas Graf		nl_cb_set(cb, i, kind, NULL, NULL);
22144d362409d5469aed47d19e7908d19bd194493aThomas Graf
22244d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_cb_err(cb, kind, NULL, NULL);
22344d362409d5469aed47d19e7908d19bd194493aThomas Graf
22444d362409d5469aed47d19e7908d19bd194493aThomas Graf	return cb;
22544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
22644d362409d5469aed47d19e7908d19bd194493aThomas Graf
22744d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
22844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Clone an existing callback handle
22944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg orig		original callback handle
23044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Newly allocated callback handle being a duplicate of
23144d362409d5469aed47d19e7908d19bd194493aThomas Graf *         orig or NULL
23244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
23344d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_cb *nl_cb_clone(struct nl_cb *orig)
23444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
23544d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_cb *cb;
23644d362409d5469aed47d19e7908d19bd194493aThomas Graf
23744d362409d5469aed47d19e7908d19bd194493aThomas Graf	cb = nl_cb_alloc(NL_CB_DEFAULT);
23844d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (!cb)
23944d362409d5469aed47d19e7908d19bd194493aThomas Graf		return NULL;
24044d362409d5469aed47d19e7908d19bd194493aThomas Graf
24144d362409d5469aed47d19e7908d19bd194493aThomas Graf	memcpy(cb, orig, sizeof(*orig));
24244d362409d5469aed47d19e7908d19bd194493aThomas Graf	cb->cb_refcnt = 1;
24344d362409d5469aed47d19e7908d19bd194493aThomas Graf
24444d362409d5469aed47d19e7908d19bd194493aThomas Graf	return cb;
24544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
24644d362409d5469aed47d19e7908d19bd194493aThomas Graf
24744d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_cb *nl_cb_get(struct nl_cb *cb)
24844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
24944d362409d5469aed47d19e7908d19bd194493aThomas Graf	cb->cb_refcnt++;
25044d362409d5469aed47d19e7908d19bd194493aThomas Graf
25144d362409d5469aed47d19e7908d19bd194493aThomas Graf	return cb;
25244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
25344d362409d5469aed47d19e7908d19bd194493aThomas Graf
25444d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nl_cb_put(struct nl_cb *cb)
25544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
25644d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (!cb)
25744d362409d5469aed47d19e7908d19bd194493aThomas Graf		return;
25844d362409d5469aed47d19e7908d19bd194493aThomas Graf
25944d362409d5469aed47d19e7908d19bd194493aThomas Graf	cb->cb_refcnt--;
26044d362409d5469aed47d19e7908d19bd194493aThomas Graf
26144d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (cb->cb_refcnt < 0)
26244d362409d5469aed47d19e7908d19bd194493aThomas Graf		BUG();
26344d362409d5469aed47d19e7908d19bd194493aThomas Graf
26444d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (cb->cb_refcnt <= 0)
26544d362409d5469aed47d19e7908d19bd194493aThomas Graf		free(cb);
26644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
26744d362409d5469aed47d19e7908d19bd194493aThomas Graf
26844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
26944d362409d5469aed47d19e7908d19bd194493aThomas Graf
27044d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
27144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Callback Setup
27244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
27344d362409d5469aed47d19e7908d19bd194493aThomas Graf */
27444d362409d5469aed47d19e7908d19bd194493aThomas Graf
27544d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
27644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Set up a callback
27744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cb		callback set
27844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg type		callback to modify
27944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg kind		kind of implementation
28044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg func		callback function (NL_CB_CUSTOM)
28144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg arg		argument passed to callback
28244d362409d5469aed47d19e7908d19bd194493aThomas Graf *
28344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code
28444d362409d5469aed47d19e7908d19bd194493aThomas Graf */
28544d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind,
28644d362409d5469aed47d19e7908d19bd194493aThomas Graf	      nl_recvmsg_msg_cb_t func, void *arg)
28744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
28844d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (type < 0 || type > NL_CB_TYPE_MAX)
2898a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -NLE_RANGE;
29044d362409d5469aed47d19e7908d19bd194493aThomas Graf
29144d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (kind < 0 || kind > NL_CB_KIND_MAX)
2928a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -NLE_RANGE;
29344d362409d5469aed47d19e7908d19bd194493aThomas Graf
29444d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (kind == NL_CB_CUSTOM) {
29544d362409d5469aed47d19e7908d19bd194493aThomas Graf		cb->cb_set[type] = func;
29644d362409d5469aed47d19e7908d19bd194493aThomas Graf		cb->cb_args[type] = arg;
29744d362409d5469aed47d19e7908d19bd194493aThomas Graf	} else {
29844d362409d5469aed47d19e7908d19bd194493aThomas Graf		cb->cb_set[type] = cb_def[type][kind];
29944d362409d5469aed47d19e7908d19bd194493aThomas Graf		cb->cb_args[type] = arg;
30044d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
30144d362409d5469aed47d19e7908d19bd194493aThomas Graf
30244d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
30344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
30444d362409d5469aed47d19e7908d19bd194493aThomas Graf
30544d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
30644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Set up a all callbacks
30744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cb		callback set
30844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg kind		kind of callback
30944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg func		callback function
31044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg arg		argument to be passwd to callback function
31144d362409d5469aed47d19e7908d19bd194493aThomas Graf *
31244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code
31344d362409d5469aed47d19e7908d19bd194493aThomas Graf */
31444d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind,
31544d362409d5469aed47d19e7908d19bd194493aThomas Graf		  nl_recvmsg_msg_cb_t func, void *arg)
31644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
31744d362409d5469aed47d19e7908d19bd194493aThomas Graf	int i, err;
31844d362409d5469aed47d19e7908d19bd194493aThomas Graf
31944d362409d5469aed47d19e7908d19bd194493aThomas Graf	for (i = 0; i <= NL_CB_TYPE_MAX; i++) {
32044d362409d5469aed47d19e7908d19bd194493aThomas Graf		err = nl_cb_set(cb, i, kind, func, arg);
32144d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (err < 0)
32244d362409d5469aed47d19e7908d19bd194493aThomas Graf			return err;
32344d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
32444d362409d5469aed47d19e7908d19bd194493aThomas Graf
32544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
32644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
32744d362409d5469aed47d19e7908d19bd194493aThomas Graf
32844d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
32944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Set up an error callback
33044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cb		callback set
33144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg kind		kind of callback
33244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg func		callback function
33344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg arg		argument to be passed to callback function
33444d362409d5469aed47d19e7908d19bd194493aThomas Graf */
33544d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind,
33644d362409d5469aed47d19e7908d19bd194493aThomas Graf	      nl_recvmsg_err_cb_t func, void *arg)
33744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
33844d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (kind < 0 || kind > NL_CB_KIND_MAX)
3398a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -NLE_RANGE;
34044d362409d5469aed47d19e7908d19bd194493aThomas Graf
34144d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (kind == NL_CB_CUSTOM) {
34244d362409d5469aed47d19e7908d19bd194493aThomas Graf		cb->cb_err = func;
34344d362409d5469aed47d19e7908d19bd194493aThomas Graf		cb->cb_err_arg = arg;
34444d362409d5469aed47d19e7908d19bd194493aThomas Graf	} else {
34544d362409d5469aed47d19e7908d19bd194493aThomas Graf		cb->cb_err = cb_err_def[kind];
34644d362409d5469aed47d19e7908d19bd194493aThomas Graf		cb->cb_err_arg = arg;
34744d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
34844d362409d5469aed47d19e7908d19bd194493aThomas Graf
34944d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
35044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
35144d362409d5469aed47d19e7908d19bd194493aThomas Graf
35244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
35344d362409d5469aed47d19e7908d19bd194493aThomas Graf
35444d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
35544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Overwriting
35644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
35744d362409d5469aed47d19e7908d19bd194493aThomas Graf */
35844d362409d5469aed47d19e7908d19bd194493aThomas Graf
35944d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
36044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Overwrite internal calls to nl_recvmsgs()
36144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cb		callback set
36244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg func		replacement callback for nl_recvmsgs()
36344d362409d5469aed47d19e7908d19bd194493aThomas Graf */
36444d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nl_cb_overwrite_recvmsgs(struct nl_cb *cb,
3651155370f520cb64657e25153255cf7dc1424317fThomas Graf			      int (*func)(struct nl_sock *, struct nl_cb *))
36644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
36744d362409d5469aed47d19e7908d19bd194493aThomas Graf	cb->cb_recvmsgs_ow = func;
36844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
36944d362409d5469aed47d19e7908d19bd194493aThomas Graf
37044d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
37144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Overwrite internal calls to nl_recv()
37244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cb		callback set
37344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg func		replacement callback for nl_recv()
37444d362409d5469aed47d19e7908d19bd194493aThomas Graf */
37544d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nl_cb_overwrite_recv(struct nl_cb *cb,
3761155370f520cb64657e25153255cf7dc1424317fThomas Graf			  int (*func)(struct nl_sock *, struct sockaddr_nl *,
37744d362409d5469aed47d19e7908d19bd194493aThomas Graf				      unsigned char **, struct ucred **))
37844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
37944d362409d5469aed47d19e7908d19bd194493aThomas Graf	cb->cb_recv_ow = func;
38044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
38144d362409d5469aed47d19e7908d19bd194493aThomas Graf
38244d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
38344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Overwrite internal calls to nl_send()
38444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cb		callback set
38544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg func		replacement callback for nl_send()
38644d362409d5469aed47d19e7908d19bd194493aThomas Graf */
38744d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nl_cb_overwrite_send(struct nl_cb *cb,
3881155370f520cb64657e25153255cf7dc1424317fThomas Graf			  int (*func)(struct nl_sock *, struct nl_msg *))
38944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
39044d362409d5469aed47d19e7908d19bd194493aThomas Graf	cb->cb_send_ow = func;
39144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
39244d362409d5469aed47d19e7908d19bd194493aThomas Graf
39344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
39444d362409d5469aed47d19e7908d19bd194493aThomas Graf
39544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
396