libnl 3.5.0

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