libnl  3.2.3
/build/buildd/libnl3-3.2.3/lib/handlers.c
00001 /*
00002  * lib/handlers.c       default netlink message handlers
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup core
00014  * @defgroup cb Callbacks/Customization
00015  *
00016  * @details
00017  * @par 1) Setting up a callback set
00018  * @code
00019  * // Allocate a callback set and initialize it to the verbose default set
00020  * struct nl_cb *cb = nl_cb_alloc(NL_CB_VERBOSE);
00021  *
00022  * // Modify the set to call my_func() for all valid messages
00023  * nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL);
00024  *
00025  * // Set the error message handler to the verbose default implementation
00026  * // and direct it to print all errors to the given file descriptor.
00027  * FILE *file = fopen(...);
00028  * nl_cb_err(cb, NL_CB_VERBOSE, NULL, file);
00029  * @endcode
00030  * @{
00031  */
00032 
00033 #include <netlink-local.h>
00034 #include <netlink/netlink.h>
00035 #include <netlink/utils.h>
00036 #include <netlink/msg.h>
00037 #include <netlink/handlers.h>
00038 
00039 static void print_header_content(FILE *ofd, struct nlmsghdr *n)
00040 {
00041         char flags[128];
00042         char type[32];
00043         
00044         fprintf(ofd, "type=%s length=%u flags=<%s> sequence-nr=%u pid=%u",
00045                 nl_nlmsgtype2str(n->nlmsg_type, type, sizeof(type)),
00046                 n->nlmsg_len, nl_nlmsg_flags2str(n->nlmsg_flags, flags,
00047                 sizeof(flags)), n->nlmsg_seq, n->nlmsg_pid);
00048 }
00049 
00050 static int nl_valid_handler_verbose(struct nl_msg *msg, void *arg)
00051 {
00052         FILE *ofd = arg ? arg : stdout;
00053 
00054         fprintf(ofd, "-- Warning: unhandled valid message: ");
00055         print_header_content(ofd, nlmsg_hdr(msg));
00056         fprintf(ofd, "\n");
00057 
00058         return NL_OK;
00059 }
00060 
00061 static int nl_invalid_handler_verbose(struct nl_msg *msg, void *arg)
00062 {
00063         FILE *ofd = arg ? arg : stderr;
00064 
00065         fprintf(ofd, "-- Error: Invalid message: ");
00066         print_header_content(ofd, nlmsg_hdr(msg));
00067         fprintf(ofd, "\n");
00068 
00069         return NL_STOP;
00070 }
00071 
00072 static int nl_overrun_handler_verbose(struct nl_msg *msg, void *arg)
00073 {
00074         FILE *ofd = arg ? arg : stderr;
00075 
00076         fprintf(ofd, "-- Error: Netlink Overrun: ");
00077         print_header_content(ofd, nlmsg_hdr(msg));
00078         fprintf(ofd, "\n");
00079         
00080         return NL_STOP;
00081 }
00082 
00083 static int nl_error_handler_verbose(struct sockaddr_nl *who,
00084                                     struct nlmsgerr *e, void *arg)
00085 {
00086         FILE *ofd = arg ? arg : stderr;
00087 
00088         fprintf(ofd, "-- Error received: %s\n-- Original message: ",
00089                 strerror(-e->error));
00090         print_header_content(ofd, &e->msg);
00091         fprintf(ofd, "\n");
00092 
00093         return -nl_syserr2nlerr(e->error);
00094 }
00095 
00096 static int nl_valid_handler_debug(struct nl_msg *msg, void *arg)
00097 {
00098         FILE *ofd = arg ? arg : stderr;
00099 
00100         fprintf(ofd, "-- Debug: Unhandled Valid message: ");
00101         print_header_content(ofd, nlmsg_hdr(msg));
00102         fprintf(ofd, "\n");
00103 
00104         return NL_OK;
00105 }
00106 
00107 static int nl_finish_handler_debug(struct nl_msg *msg, void *arg)
00108 {
00109         FILE *ofd = arg ? arg : stderr;
00110 
00111         fprintf(ofd, "-- Debug: End of multipart message block: ");
00112         print_header_content(ofd, nlmsg_hdr(msg));
00113         fprintf(ofd, "\n");
00114         
00115         return NL_STOP;
00116 }
00117 
00118 static int nl_msg_in_handler_debug(struct nl_msg *msg, void *arg)
00119 {
00120         FILE *ofd = arg ? arg : stderr;
00121 
00122         fprintf(ofd, "-- Debug: Received Message:\n");
00123         nl_msg_dump(msg, ofd);
00124         
00125         return NL_OK;
00126 }
00127 
00128 static int nl_msg_out_handler_debug(struct nl_msg *msg, void *arg)
00129 {
00130         FILE *ofd = arg ? arg : stderr;
00131 
00132         fprintf(ofd, "-- Debug: Sent Message:\n");
00133         nl_msg_dump(msg, ofd);
00134 
00135         return NL_OK;
00136 }
00137 
00138 static int nl_skipped_handler_debug(struct nl_msg *msg, void *arg)
00139 {
00140         FILE *ofd = arg ? arg : stderr;
00141 
00142         fprintf(ofd, "-- Debug: Skipped message: ");
00143         print_header_content(ofd, nlmsg_hdr(msg));
00144         fprintf(ofd, "\n");
00145 
00146         return NL_SKIP;
00147 }
00148 
00149 static int nl_ack_handler_debug(struct nl_msg *msg, void *arg)
00150 {
00151         FILE *ofd = arg ? arg : stderr;
00152 
00153         fprintf(ofd, "-- Debug: ACK: ");
00154         print_header_content(ofd, nlmsg_hdr(msg));
00155         fprintf(ofd, "\n");
00156 
00157         return NL_STOP;
00158 }
00159 
00160 static nl_recvmsg_msg_cb_t cb_def[NL_CB_TYPE_MAX+1][NL_CB_KIND_MAX+1] = {
00161         [NL_CB_VALID] = {
00162                 [NL_CB_VERBOSE] = nl_valid_handler_verbose,
00163                 [NL_CB_DEBUG]   = nl_valid_handler_debug,
00164         },
00165         [NL_CB_FINISH] = {
00166                 [NL_CB_DEBUG]   = nl_finish_handler_debug,
00167         },
00168         [NL_CB_INVALID] = {
00169                 [NL_CB_VERBOSE] = nl_invalid_handler_verbose,
00170                 [NL_CB_DEBUG]   = nl_invalid_handler_verbose,
00171         },
00172         [NL_CB_MSG_IN] = {
00173                 [NL_CB_DEBUG]   = nl_msg_in_handler_debug,
00174         },
00175         [NL_CB_MSG_OUT] = {
00176                 [NL_CB_DEBUG]   = nl_msg_out_handler_debug,
00177         },
00178         [NL_CB_OVERRUN] = {
00179                 [NL_CB_VERBOSE] = nl_overrun_handler_verbose,
00180                 [NL_CB_DEBUG]   = nl_overrun_handler_verbose,
00181         },
00182         [NL_CB_SKIPPED] = {
00183                 [NL_CB_DEBUG]   = nl_skipped_handler_debug,
00184         },
00185         [NL_CB_ACK] = {
00186                 [NL_CB_DEBUG]   = nl_ack_handler_debug,
00187         },
00188 };
00189 
00190 static nl_recvmsg_err_cb_t cb_err_def[NL_CB_KIND_MAX+1] = {
00191         [NL_CB_VERBOSE] = nl_error_handler_verbose,
00192         [NL_CB_DEBUG]   = nl_error_handler_verbose,
00193 };
00194 
00195 /**
00196  * @name Callback Handle Management
00197  * @{
00198  */
00199 
00200 /**
00201  * Allocate a new callback handle
00202  * @arg kind            callback kind to be used for initialization
00203  * @return Newly allocated callback handle or NULL
00204  */
00205 struct nl_cb *nl_cb_alloc(enum nl_cb_kind kind)
00206 {
00207         int i;
00208         struct nl_cb *cb;
00209 
00210         if (kind < 0 || kind > NL_CB_KIND_MAX)
00211                 return NULL;
00212 
00213         cb = calloc(1, sizeof(*cb));
00214         if (!cb)
00215                 return NULL;
00216 
00217         cb->cb_refcnt = 1;
00218 
00219         for (i = 0; i <= NL_CB_TYPE_MAX; i++)
00220                 nl_cb_set(cb, i, kind, NULL, NULL);
00221 
00222         nl_cb_err(cb, kind, NULL, NULL);
00223 
00224         return cb;
00225 }
00226 
00227 /**
00228  * Clone an existing callback handle
00229  * @arg orig            original callback handle
00230  * @return Newly allocated callback handle being a duplicate of
00231  *         orig or NULL
00232  */
00233 struct nl_cb *nl_cb_clone(struct nl_cb *orig)
00234 {
00235         struct nl_cb *cb;
00236         
00237         cb = nl_cb_alloc(NL_CB_DEFAULT);
00238         if (!cb)
00239                 return NULL;
00240 
00241         memcpy(cb, orig, sizeof(*orig));
00242         cb->cb_refcnt = 1;
00243 
00244         return cb;
00245 }
00246 
00247 struct nl_cb *nl_cb_get(struct nl_cb *cb)
00248 {
00249         cb->cb_refcnt++;
00250 
00251         return cb;
00252 }
00253 
00254 void nl_cb_put(struct nl_cb *cb)
00255 {
00256         if (!cb)
00257                 return;
00258 
00259         cb->cb_refcnt--;
00260 
00261         if (cb->cb_refcnt < 0)
00262                 BUG();
00263 
00264         if (cb->cb_refcnt <= 0)
00265                 free(cb);
00266 }
00267 
00268 /** @} */
00269 
00270 /**
00271  * @name Callback Setup
00272  * @{
00273  */
00274 
00275 /**
00276  * Set up a callback 
00277  * @arg cb              callback set
00278  * @arg type            callback to modify
00279  * @arg kind            kind of implementation
00280  * @arg func            callback function (NL_CB_CUSTOM)
00281  * @arg arg             argument passed to callback
00282  *
00283  * @return 0 on success or a negative error code
00284  */
00285 int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind,
00286               nl_recvmsg_msg_cb_t func, void *arg)
00287 {
00288         if (type < 0 || type > NL_CB_TYPE_MAX)
00289                 return -NLE_RANGE;
00290 
00291         if (kind < 0 || kind > NL_CB_KIND_MAX)
00292                 return -NLE_RANGE;
00293 
00294         if (kind == NL_CB_CUSTOM) {
00295                 cb->cb_set[type] = func;
00296                 cb->cb_args[type] = arg;
00297         } else {
00298                 cb->cb_set[type] = cb_def[type][kind];
00299                 cb->cb_args[type] = arg;
00300         }
00301 
00302         return 0;
00303 }
00304 
00305 /**
00306  * Set up a all callbacks
00307  * @arg cb              callback set
00308  * @arg kind            kind of callback
00309  * @arg func            callback function
00310  * @arg arg             argument to be passwd to callback function
00311  *
00312  * @return 0 on success or a negative error code
00313  */
00314 int nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind,
00315                   nl_recvmsg_msg_cb_t func, void *arg)
00316 {
00317         int i, err;
00318 
00319         for (i = 0; i <= NL_CB_TYPE_MAX; i++) {
00320                 err = nl_cb_set(cb, i, kind, func, arg);
00321                 if (err < 0)
00322                         return err;
00323         }
00324 
00325         return 0;
00326 }
00327 
00328 /**
00329  * Set up an error callback
00330  * @arg cb              callback set
00331  * @arg kind            kind of callback
00332  * @arg func            callback function
00333  * @arg arg             argument to be passed to callback function
00334  */
00335 int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind,
00336               nl_recvmsg_err_cb_t func, void *arg)
00337 {
00338         if (kind < 0 || kind > NL_CB_KIND_MAX)
00339                 return -NLE_RANGE;
00340 
00341         if (kind == NL_CB_CUSTOM) {
00342                 cb->cb_err = func;
00343                 cb->cb_err_arg = arg;
00344         } else {
00345                 cb->cb_err = cb_err_def[kind];
00346                 cb->cb_err_arg = arg;
00347         }
00348 
00349         return 0;
00350 }
00351 
00352 /** @} */
00353 
00354 /**
00355  * @name Overwriting
00356  * @{
00357  */
00358 
00359 /**
00360  * Overwrite internal calls to nl_recvmsgs()
00361  * @arg cb              callback set
00362  * @arg func            replacement callback for nl_recvmsgs()
00363  */
00364 void nl_cb_overwrite_recvmsgs(struct nl_cb *cb,
00365                               int (*func)(struct nl_sock *, struct nl_cb *))
00366 {
00367         cb->cb_recvmsgs_ow = func;
00368 }
00369 
00370 /**
00371  * Overwrite internal calls to nl_recv()
00372  * @arg cb              callback set
00373  * @arg func            replacement callback for nl_recv()
00374  */
00375 void nl_cb_overwrite_recv(struct nl_cb *cb,
00376                           int (*func)(struct nl_sock *, struct sockaddr_nl *,
00377                                       unsigned char **, struct ucred **))
00378 {
00379         cb->cb_recv_ow = func;
00380 }
00381 
00382 /**
00383  * Overwrite internal calls to nl_send()
00384  * @arg cb              callback set
00385  * @arg func            replacement callback for nl_send()
00386  */
00387 void nl_cb_overwrite_send(struct nl_cb *cb,
00388                           int (*func)(struct nl_sock *, struct nl_msg *))
00389 {
00390         cb->cb_send_ow = func;
00391 }
00392 
00393 /** @} */
00394 
00395 /** @} */