libnl  3.2.24-rc1
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  char buf[256];
83 
84  fprintf(ofd, "-- Error received: %s\n-- Original message: ",
85  strerror_r(-e->error, buf, sizeof(buf)));
86  print_header_content(ofd, &e->msg);
87  fprintf(ofd, "\n");
88 
89  return -nl_syserr2nlerr(e->error);
90 }
91 
92 static int nl_valid_handler_debug(struct nl_msg *msg, void *arg)
93 {
94  FILE *ofd = arg ? arg : stderr;
95 
96  fprintf(ofd, "-- Debug: Unhandled Valid message: ");
97  print_header_content(ofd, nlmsg_hdr(msg));
98  fprintf(ofd, "\n");
99 
100  return NL_OK;
101 }
102 
103 static int nl_finish_handler_debug(struct nl_msg *msg, void *arg)
104 {
105  FILE *ofd = arg ? arg : stderr;
106 
107  fprintf(ofd, "-- Debug: End of multipart message block: ");
108  print_header_content(ofd, nlmsg_hdr(msg));
109  fprintf(ofd, "\n");
110 
111  return NL_STOP;
112 }
113 
114 static int nl_msg_in_handler_debug(struct nl_msg *msg, void *arg)
115 {
116  FILE *ofd = arg ? arg : stderr;
117 
118  fprintf(ofd, "-- Debug: Received Message:\n");
119  nl_msg_dump(msg, ofd);
120 
121  return NL_OK;
122 }
123 
124 static int nl_msg_out_handler_debug(struct nl_msg *msg, void *arg)
125 {
126  FILE *ofd = arg ? arg : stderr;
127 
128  fprintf(ofd, "-- Debug: Sent Message:\n");
129  nl_msg_dump(msg, ofd);
130 
131  return NL_OK;
132 }
133 
134 static int nl_skipped_handler_debug(struct nl_msg *msg, void *arg)
135 {
136  FILE *ofd = arg ? arg : stderr;
137 
138  fprintf(ofd, "-- Debug: Skipped message: ");
139  print_header_content(ofd, nlmsg_hdr(msg));
140  fprintf(ofd, "\n");
141 
142  return NL_SKIP;
143 }
144 
145 static int nl_ack_handler_debug(struct nl_msg *msg, void *arg)
146 {
147  FILE *ofd = arg ? arg : stderr;
148 
149  fprintf(ofd, "-- Debug: ACK: ");
150  print_header_content(ofd, nlmsg_hdr(msg));
151  fprintf(ofd, "\n");
152 
153  return NL_STOP;
154 }
155 
156 static nl_recvmsg_msg_cb_t cb_def[NL_CB_TYPE_MAX+1][NL_CB_KIND_MAX+1] = {
157  [NL_CB_VALID] = {
158  [NL_CB_VERBOSE] = nl_valid_handler_verbose,
159  [NL_CB_DEBUG] = nl_valid_handler_debug,
160  },
161  [NL_CB_FINISH] = {
162  [NL_CB_DEBUG] = nl_finish_handler_debug,
163  },
164  [NL_CB_INVALID] = {
165  [NL_CB_VERBOSE] = nl_invalid_handler_verbose,
166  [NL_CB_DEBUG] = nl_invalid_handler_verbose,
167  },
168  [NL_CB_MSG_IN] = {
169  [NL_CB_DEBUG] = nl_msg_in_handler_debug,
170  },
171  [NL_CB_MSG_OUT] = {
172  [NL_CB_DEBUG] = nl_msg_out_handler_debug,
173  },
174  [NL_CB_OVERRUN] = {
175  [NL_CB_VERBOSE] = nl_overrun_handler_verbose,
176  [NL_CB_DEBUG] = nl_overrun_handler_verbose,
177  },
178  [NL_CB_SKIPPED] = {
179  [NL_CB_DEBUG] = nl_skipped_handler_debug,
180  },
181  [NL_CB_ACK] = {
182  [NL_CB_DEBUG] = nl_ack_handler_debug,
183  },
184 };
185 
186 static nl_recvmsg_err_cb_t cb_err_def[NL_CB_KIND_MAX+1] = {
187  [NL_CB_VERBOSE] = nl_error_handler_verbose,
188  [NL_CB_DEBUG] = nl_error_handler_verbose,
189 };
190 
191 /**
192  * @name Callback Handle Management
193  * @{
194  */
195 
196 /**
197  * Allocate a new callback handle
198  * @arg kind callback kind to be used for initialization
199  * @return Newly allocated callback handle or NULL
200  */
201 struct nl_cb *nl_cb_alloc(enum nl_cb_kind kind)
202 {
203  int i;
204  struct nl_cb *cb;
205 
206  if (kind < 0 || kind > NL_CB_KIND_MAX)
207  return NULL;
208 
209  cb = calloc(1, sizeof(*cb));
210  if (!cb)
211  return NULL;
212 
213  cb->cb_refcnt = 1;
214  cb->cb_active = NL_CB_TYPE_MAX + 1;
215 
216  for (i = 0; i <= NL_CB_TYPE_MAX; i++)
217  nl_cb_set(cb, i, kind, NULL, NULL);
218 
219  nl_cb_err(cb, kind, NULL, NULL);
220 
221  return cb;
222 }
223 
224 /**
225  * Clone an existing callback handle
226  * @arg orig original callback handle
227  * @return Newly allocated callback handle being a duplicate of
228  * orig or NULL
229  */
230 struct nl_cb *nl_cb_clone(struct nl_cb *orig)
231 {
232  struct nl_cb *cb;
233 
235  if (!cb)
236  return NULL;
237 
238  memcpy(cb, orig, sizeof(*orig));
239  cb->cb_refcnt = 1;
240 
241  return cb;
242 }
243 
244 struct nl_cb *nl_cb_get(struct nl_cb *cb)
245 {
246  cb->cb_refcnt++;
247 
248  return cb;
249 }
250 
251 void nl_cb_put(struct nl_cb *cb)
252 {
253  if (!cb)
254  return;
255 
256  cb->cb_refcnt--;
257 
258  if (cb->cb_refcnt < 0)
259  BUG();
260 
261  if (cb->cb_refcnt <= 0)
262  free(cb);
263 }
264 
265 /**
266  * Obtain type of current active callback
267  * @arg cb callback to query
268  *
269  * @return type or __NL_CB_TYPE_MAX if none active
270  */
271 enum nl_cb_type nl_cb_active_type(struct nl_cb *cb)
272 {
273  return cb->cb_active;
274 }
275 
276 /** @} */
277 
278 /**
279  * @name Callback Setup
280  * @{
281  */
282 
283 /**
284  * Set up a callback
285  * @arg cb callback set
286  * @arg type callback to modify
287  * @arg kind kind of implementation
288  * @arg func callback function (NL_CB_CUSTOM)
289  * @arg arg argument passed to callback
290  *
291  * @return 0 on success or a negative error code
292  */
293 int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind,
294  nl_recvmsg_msg_cb_t func, void *arg)
295 {
296  if (type < 0 || type > NL_CB_TYPE_MAX)
297  return -NLE_RANGE;
298 
299  if (kind < 0 || kind > NL_CB_KIND_MAX)
300  return -NLE_RANGE;
301 
302  if (kind == NL_CB_CUSTOM) {
303  cb->cb_set[type] = func;
304  cb->cb_args[type] = arg;
305  } else {
306  cb->cb_set[type] = cb_def[type][kind];
307  cb->cb_args[type] = arg;
308  }
309 
310  return 0;
311 }
312 
313 /**
314  * Set up a all callbacks
315  * @arg cb callback set
316  * @arg kind kind of callback
317  * @arg func callback function
318  * @arg arg argument to be passwd to callback function
319  *
320  * @return 0 on success or a negative error code
321  */
322 int nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind,
323  nl_recvmsg_msg_cb_t func, void *arg)
324 {
325  int i, err;
326 
327  for (i = 0; i <= NL_CB_TYPE_MAX; i++) {
328  err = nl_cb_set(cb, i, kind, func, arg);
329  if (err < 0)
330  return err;
331  }
332 
333  return 0;
334 }
335 
336 /**
337  * Set up an error callback
338  * @arg cb callback set
339  * @arg kind kind of callback
340  * @arg func callback function
341  * @arg arg argument to be passed to callback function
342  */
343 int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind,
344  nl_recvmsg_err_cb_t func, void *arg)
345 {
346  if (kind < 0 || kind > NL_CB_KIND_MAX)
347  return -NLE_RANGE;
348 
349  if (kind == NL_CB_CUSTOM) {
350  cb->cb_err = func;
351  cb->cb_err_arg = arg;
352  } else {
353  cb->cb_err = cb_err_def[kind];
354  cb->cb_err_arg = arg;
355  }
356 
357  return 0;
358 }
359 
360 /** @} */
361 
362 /**
363  * @name Overwriting
364  * @{
365  */
366 
367 /**
368  * Overwrite internal calls to nl_recvmsgs()
369  * @arg cb callback set
370  * @arg func replacement callback for nl_recvmsgs()
371  */
372 void nl_cb_overwrite_recvmsgs(struct nl_cb *cb,
373  int (*func)(struct nl_sock *, struct nl_cb *))
374 {
375  cb->cb_recvmsgs_ow = func;
376 }
377 
378 /**
379  * Overwrite internal calls to nl_recv()
380  * @arg cb callback set
381  * @arg func replacement callback for nl_recv()
382  */
383 void nl_cb_overwrite_recv(struct nl_cb *cb,
384  int (*func)(struct nl_sock *, struct sockaddr_nl *,
385  unsigned char **, struct ucred **))
386 {
387  cb->cb_recv_ow = func;
388 }
389 
390 /**
391  * Overwrite internal calls to nl_send()
392  * @arg cb callback set
393  * @arg func replacement callback for nl_send()
394  */
395 void nl_cb_overwrite_send(struct nl_cb *cb,
396  int (*func)(struct nl_sock *, struct nl_msg *))
397 {
398  cb->cb_send_ow = func;
399 }
400 
401 /** @} */
402 
403 /** @} */