libnl  3.6.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 
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 /** @} */
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
struct nl_cb * nl_cb_clone(struct nl_cb *orig)
Clone an existing callback handle.
Definition: handlers.c:224
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_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