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