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/**
40 * @name Callback Handle Management
41 * @{
42 */
43
44/**
45 * Allocate a new callback handle
46 * @arg kind		callback kind to be used for initialization
47 * @return Newly allocated callback handle or NULL
48 */
49struct nl_cb *nl_cb_alloc(enum nl_cb_kind kind)
50{
51	int i;
52	struct nl_cb *cb;
53
54	if (kind < 0 || kind > NL_CB_KIND_MAX)
55		return NULL;
56
57	cb = calloc(1, sizeof(*cb));
58	if (!cb)
59		return NULL;
60
61	cb->cb_refcnt = 1;
62
63	for (i = 0; i <= NL_CB_TYPE_MAX; i++)
64		nl_cb_set(cb, i, kind, NULL, NULL);
65
66	nl_cb_err(cb, kind, NULL, NULL);
67
68	return cb;
69}
70
71/**
72 * Clone an existing callback handle
73 * @arg orig		original callback handle
74 * @return Newly allocated callback handle being a duplicate of
75 *         orig or NULL
76 */
77struct nl_cb *nl_cb_clone(struct nl_cb *orig)
78{
79	struct nl_cb *cb;
80
81	cb = nl_cb_alloc(NL_CB_DEFAULT);
82	if (!cb)
83		return NULL;
84
85	memcpy(cb, orig, sizeof(*orig));
86	cb->cb_refcnt = 1;
87
88	return cb;
89}
90
91void nl_cb_put(struct nl_cb *cb)
92{
93	if (!cb)
94		return;
95
96	cb->cb_refcnt--;
97
98	if (cb->cb_refcnt < 0)
99		BUG();
100
101	if (cb->cb_refcnt <= 0)
102		free(cb);
103}
104
105/** @} */
106
107/**
108 * @name Callback Setup
109 * @{
110 */
111
112/**
113 * Set up a callback
114 * @arg cb		callback set
115 * @arg type		callback to modify
116 * @arg kind		kind of implementation
117 * @arg func		callback function (NL_CB_CUSTOM)
118 * @arg arg		argument passed to callback
119 *
120 * @return 0 on success or a negative error code
121 */
122int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind,
123	      nl_recvmsg_msg_cb_t func, void *arg)
124{
125	if (type < 0 || type > NL_CB_TYPE_MAX)
126		return -NLE_RANGE;
127
128	if (kind < 0 || kind > NL_CB_KIND_MAX)
129		return -NLE_RANGE;
130
131	if (kind == NL_CB_CUSTOM) {
132		cb->cb_set[type] = func;
133		cb->cb_args[type] = arg;
134	}
135
136	return 0;
137}
138
139/**
140 * Set up an error callback
141 * @arg cb		callback set
142 * @arg kind		kind of callback
143 * @arg func		callback function
144 * @arg arg		argument to be passed to callback function
145 */
146int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind,
147	      nl_recvmsg_err_cb_t func, void *arg)
148{
149	if (kind < 0 || kind > NL_CB_KIND_MAX)
150		return -NLE_RANGE;
151
152	if (kind == NL_CB_CUSTOM) {
153		cb->cb_err = func;
154		cb->cb_err_arg = arg;
155	}
156
157	return 0;
158}
159
160/** @} */
161
162/** @} */
163