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 
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 /** @} */
Report received that data was lost.
Definition: handlers.h:99
Called for every message sent out except for nl_sendto()
Definition: handlers.h:107
Message is an acknowledge.
Definition: handlers.h:103
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
Customized handler specified by the user.
Definition: handlers.h:83
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
Message wants to be skipped.
Definition: handlers.h:101
Stop parsing altogether and discard remaining messages.
Definition: handlers.h:68
Called for every message received.
Definition: handlers.h:105
nl_cb_kind
Callback kinds.
Definition: handlers.h:75
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
struct nl_cb * nl_cb_clone(struct nl_cb *orig)
Clone an existing callback handle.
Definition: handlers.c:231
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
Message is malformed and invalid.
Definition: handlers.h:109
void nl_msg_dump(struct nl_msg *msg, FILE *ofd)
Dump message in human readable format to file descriptor.
Definition: msg.c:976
Skip this message.
Definition: handlers.h:66
Last message in a series of multi part messages received.
Definition: handlers.h:97
struct nlmsghdr * nlmsg_hdr(struct nl_msg *n)
Return actual netlink message.
Definition: msg.c:543
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
Debug handlers for debugging.
Definition: handlers.h:81
int(* nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg)
nl_recvmsgs() callback for message processing customization
Definition: handlers.h:44
Message is valid.
Definition: handlers.h:95
Proceed with wathever would come next.
Definition: handlers.h:64
nl_cb_type
Callback types.
Definition: handlers.h:93
struct nl_cb * nl_cb_alloc(enum nl_cb_kind kind)
Allocate a new callback handle.
Definition: handlers.c:202
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
enum nl_cb_type nl_cb_active_type(struct nl_cb *cb)
Obtain type of current active callback.
Definition: handlers.c:272
Default handlers (quiet)
Definition: handlers.h:77
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
Verbose default handlers (error messages printed)
Definition: handlers.h:79