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