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  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 
215  for (i = 0; i <= NL_CB_TYPE_MAX; i++)
216  nl_cb_set(cb, i, kind, NULL, NULL);
217 
218  nl_cb_err(cb, kind, NULL, NULL);
219 
220  return cb;
221 }
222 
223 /**
224  * Clone an existing callback handle
225  * @arg orig original callback handle
226  * @return Newly allocated callback handle being a duplicate of
227  * orig or NULL
228  */
229 struct nl_cb *nl_cb_clone(struct nl_cb *orig)
230 {
231  struct nl_cb *cb;
232 
234  if (!cb)
235  return NULL;
236 
237  memcpy(cb, orig, sizeof(*orig));
238  cb->cb_refcnt = 1;
239 
240  return cb;
241 }
242 
243 struct nl_cb *nl_cb_get(struct nl_cb *cb)
244 {
245  cb->cb_refcnt++;
246 
247  return cb;
248 }
249 
250 void nl_cb_put(struct nl_cb *cb)
251 {
252  if (!cb)
253  return;
254 
255  cb->cb_refcnt--;
256 
257  if (cb->cb_refcnt < 0)
258  BUG();
259 
260  if (cb->cb_refcnt <= 0)
261  free(cb);
262 }
263 
264 /** @} */
265 
266 /**
267  * @name Callback Setup
268  * @{
269  */
270 
271 /**
272  * Set up a callback
273  * @arg cb callback set
274  * @arg type callback to modify
275  * @arg kind kind of implementation
276  * @arg func callback function (NL_CB_CUSTOM)
277  * @arg arg argument passed to callback
278  *
279  * @return 0 on success or a negative error code
280  */
281 int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind,
282  nl_recvmsg_msg_cb_t func, void *arg)
283 {
284  if (type < 0 || type > NL_CB_TYPE_MAX)
285  return -NLE_RANGE;
286 
287  if (kind < 0 || kind > NL_CB_KIND_MAX)
288  return -NLE_RANGE;
289 
290  if (kind == NL_CB_CUSTOM) {
291  cb->cb_set[type] = func;
292  cb->cb_args[type] = arg;
293  } else {
294  cb->cb_set[type] = cb_def[type][kind];
295  cb->cb_args[type] = arg;
296  }
297 
298  return 0;
299 }
300 
301 /**
302  * Set up a all callbacks
303  * @arg cb callback set
304  * @arg kind kind of callback
305  * @arg func callback function
306  * @arg arg argument to be passwd to callback function
307  *
308  * @return 0 on success or a negative error code
309  */
310 int nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind,
311  nl_recvmsg_msg_cb_t func, void *arg)
312 {
313  int i, err;
314 
315  for (i = 0; i <= NL_CB_TYPE_MAX; i++) {
316  err = nl_cb_set(cb, i, kind, func, arg);
317  if (err < 0)
318  return err;
319  }
320 
321  return 0;
322 }
323 
324 /**
325  * Set up an error callback
326  * @arg cb callback set
327  * @arg kind kind of callback
328  * @arg func callback function
329  * @arg arg argument to be passed to callback function
330  */
331 int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind,
332  nl_recvmsg_err_cb_t func, void *arg)
333 {
334  if (kind < 0 || kind > NL_CB_KIND_MAX)
335  return -NLE_RANGE;
336 
337  if (kind == NL_CB_CUSTOM) {
338  cb->cb_err = func;
339  cb->cb_err_arg = arg;
340  } else {
341  cb->cb_err = cb_err_def[kind];
342  cb->cb_err_arg = arg;
343  }
344 
345  return 0;
346 }
347 
348 /** @} */
349 
350 /**
351  * @name Overwriting
352  * @{
353  */
354 
355 /**
356  * Overwrite internal calls to nl_recvmsgs()
357  * @arg cb callback set
358  * @arg func replacement callback for nl_recvmsgs()
359  */
360 void nl_cb_overwrite_recvmsgs(struct nl_cb *cb,
361  int (*func)(struct nl_sock *, struct nl_cb *))
362 {
363  cb->cb_recvmsgs_ow = func;
364 }
365 
366 /**
367  * Overwrite internal calls to nl_recv()
368  * @arg cb callback set
369  * @arg func replacement callback for nl_recv()
370  */
371 void nl_cb_overwrite_recv(struct nl_cb *cb,
372  int (*func)(struct nl_sock *, struct sockaddr_nl *,
373  unsigned char **, struct ucred **))
374 {
375  cb->cb_recv_ow = func;
376 }
377 
378 /**
379  * Overwrite internal calls to nl_send()
380  * @arg cb callback set
381  * @arg func replacement callback for nl_send()
382  */
383 void nl_cb_overwrite_send(struct nl_cb *cb,
384  int (*func)(struct nl_sock *, struct nl_msg *))
385 {
386  cb->cb_send_ow = func;
387 }
388 
389 /** @} */
390 
391 /** @} */