libnl: /data/src/libnl3/lib/handlers.c Source File

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
29 static 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
40 static 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
51 static 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
62 static 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
73 static 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
86 static 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
97 static 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
108 static 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
118 static 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
128 static 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
139 static 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
150 static 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
180 static 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 */
195 struct 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 */
224 struct nl_cb *nl_cb_clone(struct nl_cb *orig)
225 {
226 struct nl_cb *cb;
227
228 cb = nl_cb_alloc(NL_CB_DEFAULT);
229 if (!cb)
230 return NULL;
231
232 memcpy(cb, orig, sizeof(*orig));
233 cb->cb_refcnt = 1;
234
235 return cb;
236 }
237
238 struct nl_cb *nl_cb_get(struct nl_cb *cb)
239 {
240 cb->cb_refcnt++;
241
242 return cb;
243 }
244
245 void 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 */
265 enum 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 */
287 int 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 */
316 int 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 */
337 int 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 */
366 void 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 */
377 void 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 */
389 void 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 /** @} */
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:389
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:47
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:377
nl_cb_type
nl_cb_type
Callback types.
Definition: handlers.h:87
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:38
nl_cb_kind
nl_cb_kind
Callback kinds.
Definition: handlers.h:69
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:287
nl_cb_clone
struct nl_cb * nl_cb_clone(struct nl_cb *orig)
Clone an existing callback handle.
Definition: handlers.c:224
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:316
nl_cb_alloc
struct nl_cb * nl_cb_alloc(enum nl_cb_kind kind)
Allocate a new callback handle.
Definition: handlers.c:195
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:265
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:366
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:337
NL_STOP
@ NL_STOP
Stop parsing altogether and discard remaining messages.
Definition: handlers.h:62
NL_OK
@ NL_OK
Proceed with whatever would come next.
Definition: handlers.h:58
NL_SKIP
@ NL_SKIP
Skip this message.
Definition: handlers.h:60
NL_CB_SKIPPED
@ NL_CB_SKIPPED
Message wants to be skipped.
Definition: handlers.h:95
NL_CB_FINISH
@ NL_CB_FINISH
Last message in a series of multi part messages received.
Definition: handlers.h:91
NL_CB_MSG_OUT
@ NL_CB_MSG_OUT
Called for every message sent out except for nl_sendto()
Definition: handlers.h:101
NL_CB_MSG_IN
@ NL_CB_MSG_IN
Called for every message received.
Definition: handlers.h:99
NL_CB_OVERRUN
@ NL_CB_OVERRUN
Report received that data was lost.
Definition: handlers.h:93
NL_CB_VALID
@ NL_CB_VALID
Message is valid.
Definition: handlers.h:89
NL_CB_ACK
@ NL_CB_ACK
Message is an acknowledgement.
Definition: handlers.h:97
NL_CB_INVALID
@ NL_CB_INVALID
Message is malformed and invalid.
Definition: handlers.h:103
NL_CB_DEFAULT
@ NL_CB_DEFAULT
Default handlers (quiet)
Definition: handlers.h:71
NL_CB_CUSTOM
@ NL_CB_CUSTOM
Customized handler specified by the user.
Definition: handlers.h:77
NL_CB_VERBOSE
@ NL_CB_VERBOSE
Verbose default handlers (error messages printed)
Definition: handlers.h:73
NL_CB_DEBUG
@ NL_CB_DEBUG
Debug handlers for debugging.
Definition: handlers.h:75
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:969
nlmsg_hdr
struct nlmsghdr * nlmsg_hdr(struct nl_msg *n)
Return actual netlink message.
Definition: msg.c:536