libnl 3.7.0
handlers.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
4 */
5
6/**
7 * @ingroup core
8 * @defgroup cb Callbacks/Customization
9 *
10 * Related sections in the development guide:
11 * - @core_doc{core_cb, Callback Configuration}
12 *
13 * @{
14 *
15 * Header
16 * ------
17 * ~~~~{.c}
18 * #include <netlink/handlers.h>
19 * ~~~~
20 */
21
22#include <netlink-private/netlink.h>
23#include <netlink-private/utils.h>
24#include <netlink/netlink.h>
25#include <netlink/utils.h>
26#include <netlink/msg.h>
27#include <netlink/handlers.h>
28
29static void print_header_content(FILE *ofd, struct nlmsghdr *n)
30{
31 char flags[128];
32 char type[32];
33
34 fprintf(ofd, "type=%s length=%u flags=<%s> sequence-nr=%u pid=%u",
35 nl_nlmsgtype2str(n->nlmsg_type, type, sizeof(type)),
36 n->nlmsg_len, nl_nlmsg_flags2str(n->nlmsg_flags, flags,
37 sizeof(flags)), n->nlmsg_seq, n->nlmsg_pid);
38}
39
40static int nl_valid_handler_verbose(struct nl_msg *msg, void *arg)
41{
42 FILE *ofd = arg ? arg : stdout;
43
44 fprintf(ofd, "-- Warning: unhandled valid message: ");
45 print_header_content(ofd, nlmsg_hdr(msg));
46 fprintf(ofd, "\n");
47
48 return NL_OK;
49}
50
51static int nl_invalid_handler_verbose(struct nl_msg *msg, void *arg)
52{
53 FILE *ofd = arg ? arg : stderr;
54
55 fprintf(ofd, "-- Error: Invalid message: ");
56 print_header_content(ofd, nlmsg_hdr(msg));
57 fprintf(ofd, "\n");
58
59 return NL_STOP;
60}
61
62static int nl_overrun_handler_verbose(struct nl_msg *msg, void *arg)
63{
64 FILE *ofd = arg ? arg : stderr;
65
66 fprintf(ofd, "-- Error: Netlink Overrun: ");
67 print_header_content(ofd, nlmsg_hdr(msg));
68 fprintf(ofd, "\n");
69
70 return NL_STOP;
71}
72
73static int nl_error_handler_verbose(struct sockaddr_nl *who,
74 struct nlmsgerr *e, void *arg)
75{
76 FILE *ofd = arg ? arg : stderr;
77
78 fprintf(ofd, "-- Error received: %s\n-- Original message: ",
79 nl_strerror_l(-e->error));
80 print_header_content(ofd, &e->msg);
81 fprintf(ofd, "\n");
82
83 return -nl_syserr2nlerr(e->error);
84}
85
86static int nl_valid_handler_debug(struct nl_msg *msg, void *arg)
87{
88 FILE *ofd = arg ? arg : stderr;
89
90 fprintf(ofd, "-- Debug: Unhandled Valid message: ");
91 print_header_content(ofd, nlmsg_hdr(msg));
92 fprintf(ofd, "\n");
93
94 return NL_OK;
95}
96
97static int nl_finish_handler_debug(struct nl_msg *msg, void *arg)
98{
99 FILE *ofd = arg ? arg : stderr;
100
101 fprintf(ofd, "-- Debug: End of multipart message block: ");
102 print_header_content(ofd, nlmsg_hdr(msg));
103 fprintf(ofd, "\n");
104
105 return NL_STOP;
106}
107
108static int nl_msg_in_handler_debug(struct nl_msg *msg, void *arg)
109{
110 FILE *ofd = arg ? arg : stderr;
111
112 fprintf(ofd, "-- Debug: Received Message:\n");
113 nl_msg_dump(msg, ofd);
114
115 return NL_OK;
116}
117
118static int nl_msg_out_handler_debug(struct nl_msg *msg, void *arg)
119{
120 FILE *ofd = arg ? arg : stderr;
121
122 fprintf(ofd, "-- Debug: Sent Message:\n");
123 nl_msg_dump(msg, ofd);
124
125 return NL_OK;
126}
127
128static int nl_skipped_handler_debug(struct nl_msg *msg, void *arg)
129{
130 FILE *ofd = arg ? arg : stderr;
131
132 fprintf(ofd, "-- Debug: Skipped message: ");
133 print_header_content(ofd, nlmsg_hdr(msg));
134 fprintf(ofd, "\n");
135
136 return NL_SKIP;
137}
138
139static int nl_ack_handler_debug(struct nl_msg *msg, void *arg)
140{
141 FILE *ofd = arg ? arg : stderr;
142
143 fprintf(ofd, "-- Debug: ACK: ");
144 print_header_content(ofd, nlmsg_hdr(msg));
145 fprintf(ofd, "\n");
146
147 return NL_STOP;
148}
149
150static nl_recvmsg_msg_cb_t cb_def[NL_CB_TYPE_MAX+1][NL_CB_KIND_MAX+1] = {
151 [NL_CB_VALID] = {
152 [NL_CB_VERBOSE] = nl_valid_handler_verbose,
153 [NL_CB_DEBUG] = nl_valid_handler_debug,
154 },
155 [NL_CB_FINISH] = {
156 [NL_CB_DEBUG] = nl_finish_handler_debug,
157 },
158 [NL_CB_INVALID] = {
159 [NL_CB_VERBOSE] = nl_invalid_handler_verbose,
160 [NL_CB_DEBUG] = nl_invalid_handler_verbose,
161 },
162 [NL_CB_MSG_IN] = {
163 [NL_CB_DEBUG] = nl_msg_in_handler_debug,
164 },
165 [NL_CB_MSG_OUT] = {
166 [NL_CB_DEBUG] = nl_msg_out_handler_debug,
167 },
168 [NL_CB_OVERRUN] = {
169 [NL_CB_VERBOSE] = nl_overrun_handler_verbose,
170 [NL_CB_DEBUG] = nl_overrun_handler_verbose,
171 },
172 [NL_CB_SKIPPED] = {
173 [NL_CB_DEBUG] = nl_skipped_handler_debug,
174 },
175 [NL_CB_ACK] = {
176 [NL_CB_DEBUG] = nl_ack_handler_debug,
177 },
178};
179
180static nl_recvmsg_err_cb_t cb_err_def[NL_CB_KIND_MAX+1] = {
181 [NL_CB_VERBOSE] = nl_error_handler_verbose,
182 [NL_CB_DEBUG] = nl_error_handler_verbose,
183};
184
185/**
186 * @name Callback Handle Management
187 * @{
188 */
189
190/**
191 * Allocate a new callback handle
192 * @arg kind callback kind to be used for initialization
193 * @return Newly allocated callback handle or NULL
194 */
195struct nl_cb *nl_cb_alloc(enum nl_cb_kind kind)
196{
197 int i;
198 struct nl_cb *cb;
199
200 if ((unsigned int) kind > NL_CB_KIND_MAX)
201 return NULL;
202
203 cb = calloc(1, sizeof(*cb));
204 if (!cb)
205 return NULL;
206
207 cb->cb_refcnt = 1;
208 cb->cb_active = NL_CB_TYPE_MAX + 1;
209
210 for (i = 0; i <= NL_CB_TYPE_MAX; i++)
211 nl_cb_set(cb, i, kind, NULL, NULL);
212
213 nl_cb_err(cb, kind, NULL, NULL);
214
215 return cb;
216}
217
218/**
219 * Clone an existing callback handle
220 * @arg orig original callback handle
221 * @return Newly allocated callback handle being a duplicate of
222 * orig or NULL
223 */
224struct nl_cb *nl_cb_clone(struct nl_cb *orig)
225{
226 struct nl_cb *cb;
227
229 if (!cb)
230 return NULL;
231
232 memcpy(cb, orig, sizeof(*orig));
233 cb->cb_refcnt = 1;
234
235 return cb;
236}
237
238struct nl_cb *nl_cb_get(struct nl_cb *cb)
239{
240 cb->cb_refcnt++;
241
242 return cb;
243}
244
245void nl_cb_put(struct nl_cb *cb)
246{
247 if (!cb)
248 return;
249
250 cb->cb_refcnt--;
251
252 if (cb->cb_refcnt < 0)
253 BUG();
254
255 if (cb->cb_refcnt <= 0)
256 free(cb);
257}
258
259/**
260 * Obtain type of current active callback
261 * @arg cb callback to query
262 *
263 * @return type or __NL_CB_TYPE_MAX if none active
264 */
265enum nl_cb_type nl_cb_active_type(struct nl_cb *cb)
266{
267 return cb->cb_active;
268}
269
270/** @} */
271
272/**
273 * @name Callback Setup
274 * @{
275 */
276
277/**
278 * Set up a callback
279 * @arg cb callback set
280 * @arg type callback to modify
281 * @arg kind kind of implementation
282 * @arg func callback function (NL_CB_CUSTOM)
283 * @arg arg argument passed to callback
284 *
285 * @return 0 on success or a negative error code
286 */
287int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind,
288 nl_recvmsg_msg_cb_t func, void *arg)
289{
290 if ((unsigned int) type > NL_CB_TYPE_MAX)
291 return -NLE_RANGE;
292
293 if ((unsigned int) kind > NL_CB_KIND_MAX)
294 return -NLE_RANGE;
295
296 if (kind == NL_CB_CUSTOM) {
297 cb->cb_set[type] = func;
298 cb->cb_args[type] = arg;
299 } else {
300 cb->cb_set[type] = cb_def[type][kind];
301 cb->cb_args[type] = arg;
302 }
303
304 return 0;
305}
306
307/**
308 * Set up a all callbacks
309 * @arg cb callback set
310 * @arg kind kind of callback
311 * @arg func callback function
312 * @arg arg argument to be passwd to callback function
313 *
314 * @return 0 on success or a negative error code
315 */
316int nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind,
317 nl_recvmsg_msg_cb_t func, void *arg)
318{
319 int i, err;
320
321 for (i = 0; i <= NL_CB_TYPE_MAX; i++) {
322 err = nl_cb_set(cb, i, kind, func, arg);
323 if (err < 0)
324 return err;
325 }
326
327 return 0;
328}
329
330/**
331 * Set up an error callback
332 * @arg cb callback set
333 * @arg kind kind of callback
334 * @arg func callback function
335 * @arg arg argument to be passed to callback function
336 */
337int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind,
338 nl_recvmsg_err_cb_t func, void *arg)
339{
340 if ((unsigned int) kind > NL_CB_KIND_MAX)
341 return -NLE_RANGE;
342
343 if (kind == NL_CB_CUSTOM) {
344 cb->cb_err = func;
345 cb->cb_err_arg = arg;
346 } else {
347 cb->cb_err = cb_err_def[kind];
348 cb->cb_err_arg = arg;
349 }
350
351 return 0;
352}
353
354/** @} */
355
356/**
357 * @name Overwriting
358 * @{
359 */
360
361/**
362 * Overwrite internal calls to nl_recvmsgs()
363 * @arg cb callback set
364 * @arg func replacement callback for nl_recvmsgs()
365 */
366void nl_cb_overwrite_recvmsgs(struct nl_cb *cb,
367 int (*func)(struct nl_sock *, struct nl_cb *))
368{
369 cb->cb_recvmsgs_ow = func;
370}
371
372/**
373 * Overwrite internal calls to nl_recv()
374 * @arg cb callback set
375 * @arg func replacement callback for nl_recv()
376 */
377void nl_cb_overwrite_recv(struct nl_cb *cb,
378 int (*func)(struct nl_sock *, struct sockaddr_nl *,
379 unsigned char **, struct ucred **))
380{
381 cb->cb_recv_ow = func;
382}
383
384/**
385 * Overwrite internal calls to nl_send()
386 * @arg cb callback set
387 * @arg func replacement callback for nl_send()
388 */
389void nl_cb_overwrite_send(struct nl_cb *cb,
390 int (*func)(struct nl_sock *, struct nl_msg *))
391{
392 cb->cb_send_ow = func;
393}
394
395/** @} */
396
397/** @} */
void nl_cb_overwrite_send(struct nl_cb *cb, int(*func)(struct nl_sock *, struct nl_msg *))
Overwrite internal calls to nl_send()
Definition: handlers.c:389
int(* nl_recvmsg_err_cb_t)(struct sockaddr_nl *nla, struct nlmsgerr *nlerr, void *arg)
nl_recvmsgs() callback for error message processing customization
Definition: handlers.h:47
void nl_cb_overwrite_recv(struct nl_cb *cb, int(*func)(struct nl_sock *, struct sockaddr_nl *, unsigned char **, struct ucred **))
Overwrite internal calls to nl_recv()
Definition: handlers.c:377
nl_cb_type
Callback types.
Definition: handlers.h:87
int(* nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg)
nl_recvmsgs() callback for message processing customization
Definition: handlers.h:38
nl_cb_kind
Callback kinds.
Definition: handlers.h:69
int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func, void *arg)
Set up a callback.
Definition: handlers.c:287
int nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func, void *arg)
Set up a all callbacks.
Definition: handlers.c:316
struct nl_cb * nl_cb_clone(struct nl_cb *orig)
Clone an existing callback handle.
Definition: handlers.c:224
struct nl_cb * nl_cb_alloc(enum nl_cb_kind kind)
Allocate a new callback handle.
Definition: handlers.c:195
enum nl_cb_type nl_cb_active_type(struct nl_cb *cb)
Obtain type of current active callback.
Definition: handlers.c:265
void nl_cb_overwrite_recvmsgs(struct nl_cb *cb, int(*func)(struct nl_sock *, struct nl_cb *))
Overwrite internal calls to nl_recvmsgs()
Definition: handlers.c:366
int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind, nl_recvmsg_err_cb_t func, void *arg)
Set up an error callback.
Definition: handlers.c:337
@ NL_STOP
Stop parsing altogether and discard remaining messages.
Definition: handlers.h:62
@ NL_OK
Proceed with whatever would come next.
Definition: handlers.h:58
@ NL_SKIP
Skip this message.
Definition: handlers.h:60
@ NL_CB_SKIPPED
Message wants to be skipped.
Definition: handlers.h:95
@ NL_CB_FINISH
Last message in a series of multi part messages received.
Definition: handlers.h:91
@ NL_CB_MSG_OUT
Called for every message sent out except for nl_sendto()
Definition: handlers.h:101
@ NL_CB_MSG_IN
Called for every message received.
Definition: handlers.h:99
@ NL_CB_OVERRUN
Report received that data was lost.
Definition: handlers.h:93
@ NL_CB_VALID
Message is valid.
Definition: handlers.h:89
@ NL_CB_ACK
Message is an acknowledgement.
Definition: handlers.h:97
@ NL_CB_INVALID
Message is malformed and invalid.
Definition: handlers.h:103
@ NL_CB_DEFAULT
Default handlers (quiet)
Definition: handlers.h:71
@ NL_CB_CUSTOM
Customized handler specified by the user.
Definition: handlers.h:77
@ NL_CB_VERBOSE
Verbose default handlers (error messages printed)
Definition: handlers.h:73
@ NL_CB_DEBUG
Debug handlers for debugging.
Definition: handlers.h:75
void nl_msg_dump(struct nl_msg *msg, FILE *ofd)
Dump message in human readable format to file descriptor.
Definition: msg.c:969
struct nlmsghdr * nlmsg_hdr(struct nl_msg *n)
Return actual netlink message.
Definition: msg.c:536