xref: /aosp_15_r20/external/libnl/lib/handlers.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3  * Copyright (c) 2003-2008 Thomas Graf <[email protected]>
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 
print_header_content(FILE * ofd,struct nlmsghdr * n)32 static 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 
nl_valid_handler_verbose(struct nl_msg * msg,void * arg)43 static 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 
nl_invalid_handler_verbose(struct nl_msg * msg,void * arg)54 static 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 
nl_overrun_handler_verbose(struct nl_msg * msg,void * arg)65 static 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 
nl_error_handler_verbose(struct sockaddr_nl * who,struct nlmsgerr * e,void * arg)76 static 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 
nl_valid_handler_debug(struct nl_msg * msg,void * arg)89 static 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 
nl_finish_handler_debug(struct nl_msg * msg,void * arg)100 static 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 
nl_msg_in_handler_debug(struct nl_msg * msg,void * arg)111 static 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 
nl_msg_out_handler_debug(struct nl_msg * msg,void * arg)121 static 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 
nl_skipped_handler_debug(struct nl_msg * msg,void * arg)131 static 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 
nl_ack_handler_debug(struct nl_msg * msg,void * arg)142 static 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 
153 static 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 
183 static 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  */
nl_cb_alloc(enum nl_cb_kind kind)198 struct 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  */
nl_cb_clone(struct nl_cb * orig)227 struct nl_cb *nl_cb_clone(struct nl_cb *orig)
228 {
229 	struct nl_cb *cb;
230 
231 	cb = nl_cb_alloc(NL_CB_DEFAULT);
232 	if (!cb)
233 		return NULL;
234 
235 	memcpy(cb, orig, sizeof(*orig));
236 	cb->cb_refcnt = 1;
237 
238 	return cb;
239 }
240 
nl_cb_get(struct nl_cb * cb)241 struct nl_cb *nl_cb_get(struct nl_cb *cb)
242 {
243 	cb->cb_refcnt++;
244 
245 	return cb;
246 }
247 
nl_cb_put(struct nl_cb * cb)248 void 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  */
nl_cb_active_type(struct nl_cb * cb)268 enum nl_cb_type nl_cb_active_type(struct nl_cb *cb)
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  */
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)290 int 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  */
nl_cb_set_all(struct nl_cb * cb,enum nl_cb_kind kind,nl_recvmsg_msg_cb_t func,void * arg)319 int 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  */
nl_cb_err(struct nl_cb * cb,enum nl_cb_kind kind,nl_recvmsg_err_cb_t func,void * arg)340 int 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  */
nl_cb_overwrite_recvmsgs(struct nl_cb * cb,int (* func)(struct nl_sock *,struct nl_cb *))369 void nl_cb_overwrite_recvmsgs(struct nl_cb *cb,
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  */
nl_cb_overwrite_recv(struct nl_cb * cb,int (* func)(struct nl_sock *,struct sockaddr_nl *,unsigned char **,struct ucred **))380 void nl_cb_overwrite_recv(struct nl_cb *cb,
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  */
nl_cb_overwrite_send(struct nl_cb * cb,int (* func)(struct nl_sock *,struct nl_msg *))392 void nl_cb_overwrite_send(struct nl_cb *cb,
393 			  int (*func)(struct nl_sock *, struct nl_msg *))
394 {
395 	cb->cb_send_ow = func;
396 }
397 
398 /** @} */
399 
400 /** @} */
401