/build/buildd/libnl-1.0~pre6/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-2006 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup nl
00014  * @defgroup cb Callbacks/Customization
00015  * 
00016  * Customization via callbacks.
00017  * @{
00018  */
00019 
00020 #include <netlink-local.h>
00021 #include <netlink/netlink.h>
00022 #include <netlink/utils.h>
00023 #include <netlink/msg.h>
00024 #include <netlink/handlers.h>
00025 
00026 static void print_header_content(FILE *ofd, struct nlmsghdr *n)
00027 {
00028         char flags[128];
00029         char type[32];
00030         
00031         fprintf(ofd, "type=%s length=%u flags=<%s> sequence-nr=%u pid=%u",
00032                 nl_nlmsgtype2str(n->nlmsg_type, type, sizeof(type)),
00033                 n->nlmsg_len, nl_nlmsg_flags2str(n->nlmsg_flags, flags,
00034                 sizeof(flags)), n->nlmsg_seq, n->nlmsg_pid);
00035 }
00036 
00037 static inline void dump_hex(FILE *ofd, char *start, int len)
00038 {
00039         int i, a, c, limit;
00040         char ascii[21] = {0};
00041 
00042         limit = 18;
00043         fprintf(ofd, "    ");
00044 
00045         for (i = 0, a = 0, c = 0; i < len; i++) {
00046                 int v = *(uint8_t *) (start + i);
00047 
00048                 fprintf(ofd, "%02x ", v);
00049                 ascii[a++] = isprint(v) ? v : '.';
00050 
00051                 if (c == limit-1) {
00052                         fprintf(ofd, "%s\n", ascii);
00053                         if (i < (len - 1))
00054                                 fprintf(ofd, "    ");
00055                         a = c = 0;
00056                         memset(ascii, 0, sizeof(ascii));
00057                 } else
00058                         c++;
00059         }
00060 
00061         if (c != 0) {
00062                 for (i = 0; i < (limit - c); i++)
00063                         fprintf(ofd, "   ");
00064                 fprintf(ofd, "%s\n", ascii);
00065         }
00066 }
00067 
00068 static void print_hdr(FILE *ofd, struct nl_msg *msg)
00069 {
00070         struct nlmsghdr *nlh = nlmsg_hdr(msg);
00071         struct nl_cache_ops *ops;
00072         char buf[128];
00073 
00074         fprintf(ofd, "    .nlmsg_len = %d\n", nlh->nlmsg_len);
00075 
00076         ops = nl_cache_mngt_associate(nlmsg_get_proto(msg), nlh->nlmsg_type);
00077 
00078         fprintf(ofd, "    .nlmsg_type = %d <%s>\n", nlh->nlmsg_type,
00079                 ops ? nl_cache_mngt_type2name(ops, nlh->nlmsg_type,
00080                                               buf, sizeof(buf))
00081                 : nl_nlmsgtype2str(nlh->nlmsg_type, buf, sizeof(buf)));
00082         fprintf(ofd, "    .nlmsg_flags = %d <%s>\n", nlh->nlmsg_flags,
00083                 nl_nlmsg_flags2str(nlh->nlmsg_flags, buf, sizeof(buf)));
00084         fprintf(ofd, "    .nlmsg_seq = %d\n", nlh->nlmsg_seq);
00085         fprintf(ofd, "    .nlmsg_pid = %d\n", nlh->nlmsg_pid);
00086 
00087 }
00088 
00089 static void raw_dump_msg(FILE *ofd, struct nl_msg *msg)
00090 {
00091         struct nlmsghdr *hdr = nlmsg_hdr(msg);
00092         
00093         fprintf(ofd, 
00094         "--------------------------   BEGIN NETLINK MESSAGE "
00095         "---------------------------\n");
00096 
00097         fprintf(ofd, "  [HEADER] %Zu octets\n", sizeof(struct nlmsghdr));
00098         print_hdr(ofd, msg);
00099 
00100         if (hdr->nlmsg_type == NLMSG_ERROR &&
00101             hdr->nlmsg_len >= nlmsg_msg_size(sizeof(struct nlmsgerr))) {
00102                 struct nl_msg *errmsg;
00103                 struct nlmsgerr *err = nlmsg_data(hdr);
00104 
00105                 fprintf(ofd, "  [ERRORMSG] %Zu octets\n", sizeof(*err));
00106                 fprintf(ofd, "    .error = %d \"%s\"\n", err->error,
00107                         strerror(-err->error));
00108                 fprintf(ofd, "  [ORIGINAL MESSAGE] %Zu octets\n", sizeof(*hdr));
00109 
00110                 errmsg = nlmsg_build(&err->msg);
00111                 print_hdr(ofd, errmsg);
00112                 nlmsg_free(msg);
00113         } else if (nlmsg_len(hdr) > 0) {
00114                 struct nl_cache_ops *ops;
00115                 int payloadlen = nlmsg_len(hdr);
00116                 int attrlen = 0;
00117 
00118                 ops = nl_cache_mngt_associate(nlmsg_get_proto(msg),
00119                                               hdr->nlmsg_type);
00120                 if (ops) {
00121                         attrlen = nlmsg_attrlen(hdr, ops->co_hdrsize);
00122                         payloadlen -= attrlen;
00123                 }
00124 
00125                 fprintf(ofd, "  [PAYLOAD] %d octets\n", payloadlen);
00126                 dump_hex(ofd, nlmsg_data(hdr), payloadlen);
00127 
00128                 if (attrlen) {
00129                         int rem, padlen;
00130                         struct nlattr *nla;
00131         
00132                         nlmsg_for_each_attr(nla, hdr, ops->co_hdrsize, rem) {
00133                                 int alen = nla_len(nla);
00134 
00135                                 fprintf(ofd, "  [ATTR %02d] %d octets\n",
00136                                         nla->nla_type, alen);
00137                                 dump_hex(ofd, nla_data(nla), alen);
00138 
00139                                 padlen = nla_padlen(alen);
00140                                 if (padlen > 0) {
00141                                         fprintf(ofd, "  [PADDING] %d octets\n",
00142                                                 padlen);
00143                                         dump_hex(ofd, nla_data(nla) + alen,
00144                                                  padlen);
00145                                 }
00146                         }
00147                 }
00148         }
00149 
00150         fprintf(ofd, 
00151         "---------------------------  END NETLINK MESSAGE   "
00152         "---------------------------\n");
00153 }
00154 
00155 static int nl_valid_handler_default(struct nl_msg *msg, void *arg)
00156 {
00157         return NL_PROCEED;
00158 }
00159 
00160 static int nl_finish_handler_default(struct nl_msg *msg, void *arg)
00161 {
00162         return NL_EXIT;
00163 }
00164 
00165 static int nl_invalid_handler_default(struct nl_msg *msg, void *arg)
00166 {
00167         return NL_EXIT;
00168 }
00169 
00170 static int nl_msg_in_handler_default(struct nl_msg *msg, void *arg)
00171 {
00172         return NL_PROCEED;
00173 }
00174 
00175 static int nl_msg_out_handler_default(struct nl_msg *msg, void *arg)
00176 {
00177         return NL_PROCEED;
00178 }
00179 
00180 static int nl_overrun_handler_default(struct nl_msg *msg, void *arg)
00181 {
00182         return NL_EXIT;
00183 }
00184 
00185 static int nl_skipped_handler_default(struct nl_msg *msg, void *arg)
00186 {
00187         return NL_SKIP;
00188 }
00189 
00190 static int nl_ack_handler_default(struct nl_msg *msg, void *arg)
00191 {
00192         return NL_EXIT;
00193 }
00194 
00195 static int nl_error_handler_default(struct sockaddr_nl *who,
00196                                     struct nlmsgerr *e, void *arg)
00197 {
00198         return NL_EXIT;
00199 }
00200 
00201 static int nl_valid_handler_verbose(struct nl_msg *msg, void *arg)
00202 {
00203         FILE *ofd = arg ? arg : stdout;
00204 
00205         fprintf(ofd, "-- Warning: unhandled valid message: ");
00206         print_header_content(ofd, nlmsg_hdr(msg));
00207         fprintf(ofd, "\n");
00208 
00209         return NL_PROCEED;
00210 }
00211 
00212 static int nl_finish_handler_verbose(struct nl_msg *msg, void *arg)
00213 {
00214         return NL_EXIT;
00215 }
00216 
00217 static int nl_msg_in_handler_verbose(struct nl_msg *msg, void *arg)
00218 {
00219         return NL_PROCEED;
00220 }
00221 
00222 static int nl_invalid_handler_verbose(struct nl_msg *msg, void *arg)
00223 {
00224         FILE *ofd = arg ? arg : stderr;
00225 
00226         fprintf(ofd, "-- Error: Invalid message: ");
00227         print_header_content(ofd, nlmsg_hdr(msg));
00228         fprintf(ofd, "\n");
00229 
00230         return NL_EXIT;
00231 }
00232 
00233 static int nl_msg_out_handler_verbose(struct nl_msg *msg, void *arg)
00234 {
00235         return NL_PROCEED;
00236 }
00237 
00238 static int nl_overrun_handler_verbose(struct nl_msg *msg, void *arg)
00239 {
00240         FILE *ofd = arg ? arg : stderr;
00241 
00242         fprintf(ofd, "-- Error: Netlink Overrun: ");
00243         print_header_content(ofd, nlmsg_hdr(msg));
00244         fprintf(ofd, "\n");
00245         
00246         return NL_EXIT;
00247 }
00248 
00249 static int nl_ack_handler_verbose(struct nl_msg *msg, void *arg)
00250 {
00251         return NL_EXIT;
00252 }
00253 
00254 static int nl_skipped_handler_verbose(struct nl_msg *msg, void *arg)
00255 {
00256         return NL_SKIP;
00257 }
00258 
00259 static int nl_error_handler_verbose(struct sockaddr_nl *who,
00260                                     struct nlmsgerr *e, void *arg)
00261 {
00262         FILE *ofd = arg ? arg : stderr;
00263 
00264         fprintf(ofd, "-- Error received: %s\n-- Original message: ",
00265                 strerror(-e->error));
00266         print_header_content(ofd, &e->msg);
00267         fprintf(ofd, "\n");
00268 
00269         return NL_EXIT;
00270 }
00271 
00272 static int nl_valid_handler_debug(struct nl_msg *msg, void *arg)
00273 {
00274         FILE *ofd = arg ? arg : stderr;
00275 
00276         fprintf(ofd, "-- Debug: Valid message: ");
00277         print_header_content(ofd, nlmsg_hdr(msg));
00278         fprintf(ofd, "\n");
00279 
00280         return NL_PROCEED;
00281 }
00282 
00283 static int nl_finish_handler_debug(struct nl_msg *msg, void *arg)
00284 {
00285         FILE *ofd = arg ? arg : stderr;
00286 
00287         fprintf(ofd, "-- Debug: End of multipart message block: ");
00288         print_header_content(ofd, nlmsg_hdr(msg));
00289         fprintf(ofd, "\n");
00290         
00291         return NL_EXIT;
00292 }
00293 
00294 static int nl_invalid_handler_debug(struct nl_msg *msg, void *arg)
00295 {
00296         return nl_invalid_handler_verbose(msg, arg);
00297 }
00298 
00299 static int nl_msg_in_handler_debug(struct nl_msg *msg, void *arg)
00300 {
00301         FILE *ofd = arg ? arg : stderr;
00302 
00303         fprintf(ofd, "-- Debug: Received Message:\n");
00304         raw_dump_msg(ofd, msg);
00305         
00306         return NL_PROCEED;
00307 }
00308 
00309 static int nl_msg_out_handler_debug(struct nl_msg *msg, void *arg)
00310 {
00311         FILE *ofd = arg ? arg : stderr;
00312 
00313         fprintf(ofd, "-- Debug: Sent Message:\n");
00314         raw_dump_msg(ofd, msg);
00315 
00316         return NL_PROCEED;
00317 }
00318 
00319 static int nl_overrun_handler_debug(struct nl_msg *msg, void *arg)
00320 {
00321         return nl_overrun_handler_verbose(msg, arg);
00322 }
00323 
00324 static int nl_skipped_handler_debug(struct nl_msg *msg, void *arg)
00325 {
00326         FILE *ofd = arg ? arg : stderr;
00327 
00328         fprintf(ofd, "-- Debug: Skipped message: ");
00329         print_header_content(ofd, nlmsg_hdr(msg));
00330         fprintf(ofd, "\n");
00331 
00332         return NL_SKIP;
00333 }
00334 
00335 static int nl_ack_handler_debug(struct nl_msg *msg, void *arg)
00336 {
00337         FILE *ofd = arg ? arg : stderr;
00338 
00339         fprintf(ofd, "-- Debug: ACK: ");
00340         print_header_content(ofd, nlmsg_hdr(msg));
00341         fprintf(ofd, "\n");
00342 
00343         return NL_EXIT;
00344 }
00345 
00346 static int nl_error_handler_debug(struct sockaddr_nl *who,
00347                                   struct nlmsgerr *e, void *arg)
00348 {
00349         return nl_error_handler_verbose(who, e, arg);
00350 }
00351 
00352 static nl_recvmsg_msg_cb_t cb_def[NL_CB_TYPE_MAX+1][NL_CB_KIND_MAX+1] = {
00353         [NL_CB_VALID] = {
00354                 [NL_CB_DEFAULT] = nl_valid_handler_default,
00355                 [NL_CB_VERBOSE] = nl_valid_handler_verbose,
00356                 [NL_CB_DEBUG]   = nl_valid_handler_debug,
00357         },
00358         [NL_CB_FINISH] = {
00359                 [NL_CB_DEFAULT] = nl_finish_handler_default,
00360                 [NL_CB_VERBOSE] = nl_finish_handler_verbose,
00361                 [NL_CB_DEBUG]   = nl_finish_handler_debug,
00362         },
00363         [NL_CB_INVALID] = {
00364                 [NL_CB_DEFAULT] = nl_invalid_handler_default,
00365                 [NL_CB_VERBOSE] = nl_invalid_handler_verbose,
00366                 [NL_CB_DEBUG]   = nl_invalid_handler_debug,
00367         },
00368         [NL_CB_MSG_IN] = {
00369                 [NL_CB_DEFAULT] = nl_msg_in_handler_default,
00370                 [NL_CB_VERBOSE] = nl_msg_in_handler_verbose,
00371                 [NL_CB_DEBUG]   = nl_msg_in_handler_debug,
00372         },
00373         [NL_CB_MSG_OUT] = {
00374                 [NL_CB_DEFAULT] = nl_msg_out_handler_default,
00375                 [NL_CB_VERBOSE] = nl_msg_out_handler_verbose,
00376                 [NL_CB_DEBUG]   = nl_msg_out_handler_debug,
00377         },
00378         [NL_CB_OVERRUN] = {
00379                 [NL_CB_DEFAULT] = nl_overrun_handler_default,
00380                 [NL_CB_VERBOSE] = nl_overrun_handler_verbose,
00381                 [NL_CB_DEBUG]   = nl_overrun_handler_debug,
00382         },
00383         [NL_CB_SKIPPED] = {
00384                 [NL_CB_DEFAULT] = nl_skipped_handler_default,
00385                 [NL_CB_VERBOSE] = nl_skipped_handler_verbose,
00386                 [NL_CB_DEBUG]   = nl_skipped_handler_debug,
00387         },
00388         [NL_CB_ACK] = {
00389                 [NL_CB_DEFAULT] = nl_ack_handler_default,
00390                 [NL_CB_VERBOSE] = nl_ack_handler_verbose,
00391                 [NL_CB_DEBUG]   = nl_ack_handler_debug,
00392         },
00393 };
00394 
00395 static nl_recvmsg_err_cb_t cb_err_def[NL_CB_KIND_MAX+1] = {
00396         [NL_CB_DEFAULT] = nl_error_handler_default,
00397         [NL_CB_VERBOSE] = nl_error_handler_verbose,
00398         [NL_CB_DEBUG]   = nl_error_handler_debug,
00399 };
00400 
00401 /**
00402  * @name Callback Handle Management
00403  * @{
00404  */
00405 
00406 /**
00407  * Allocate a new callback handle
00408  * @arg kind            callback kind to be used for initialization
00409  * @return Newly allocated callback handle or NULL
00410  */
00411 struct nl_cb *nl_cb_new(enum nl_cb_kind kind)
00412 {
00413         int i;
00414         struct nl_cb *cb;
00415 
00416         if (kind < 0 || kind > NL_CB_KIND_MAX)
00417                 return NULL;
00418 
00419         cb = calloc(1, sizeof(*cb));
00420         if (!cb) {
00421                 nl_errno(ENOMEM);
00422                 return NULL;
00423         }
00424 
00425         for (i = 0; i <= NL_CB_TYPE_MAX; i++)
00426                 nl_cb_set(cb, i, kind, NULL, NULL);
00427 
00428         nl_cb_err(cb, kind, NULL, NULL);
00429 
00430         return cb;
00431 }
00432 
00433 /**
00434  * Destroy a callback handle
00435  * @arg cb              callback handle
00436  */
00437 void nl_cb_destroy(struct nl_cb *cb)
00438 {
00439         free(cb);
00440 }
00441 
00442 /**
00443  * Clone an existing callback handle
00444  * @arg orig            original callback handle
00445  * @return Newly allocated callback handle being a duplicate of
00446  *         orig or NULL
00447  */
00448 struct nl_cb *nl_cb_clone(struct nl_cb *orig)
00449 {
00450         struct nl_cb *cb;
00451         
00452         cb = nl_cb_new(NL_CB_DEFAULT);
00453         if (!cb)
00454                 return NULL;
00455 
00456         memcpy(cb, orig, sizeof(*orig));
00457 
00458         return cb;
00459 }
00460 
00461 /** @} */
00462 
00463 /**
00464  * @name Callback Setup
00465  * @{
00466  */
00467 
00468 /**
00469  * Set up a callback 
00470  * @arg cb              callback configuration
00471  * @arg type            which type callback to set
00472  * @arg kind            kind of callback
00473  * @arg func            callback function
00474  * @arg arg             argument to be passwd to callback function
00475  *
00476  * @return 0 on success or a negative error code
00477  */
00478 int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind,
00479               nl_recvmsg_msg_cb_t func, void *arg)
00480 {
00481         if (type < 0 || type > NL_CB_TYPE_MAX)
00482                 return nl_error(ERANGE, "Callback type out of range");
00483 
00484         if (kind < 0 || kind > NL_CB_KIND_MAX)
00485                 return nl_error(ERANGE, "Callback kind out of range");
00486 
00487         if (kind == NL_CB_CUSTOM) {
00488                 cb->cb_set[type] = func;
00489                 cb->cb_args[type] = arg;
00490         } else {
00491                 cb->cb_set[type] = cb_def[type][kind];
00492                 cb->cb_args[type] = arg;
00493         }
00494 
00495         return 0;
00496 }
00497 
00498 /**
00499  * Set up a all callbacks
00500  * @arg cb              callback configuration
00501  * @arg kind            kind of callback
00502  * @arg func            callback function
00503  * @arg arg             argument to be passwd to callback function
00504  *
00505  * @return 0 on success or a negative error code
00506  */
00507 int nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind,
00508                   nl_recvmsg_msg_cb_t func, void *arg)
00509 {
00510         int i, err;
00511 
00512         for (i = 0; i <= NL_CB_TYPE_MAX; i++) {
00513                 err = nl_cb_set(cb, i, kind, func, arg);
00514                 if (err < 0)
00515                         return err;
00516         }
00517 
00518         return 0;
00519 }
00520 
00521 /**
00522  * Set up an error callback
00523  * @arg cb              callback configuration
00524  * @arg kind            kind of callback
00525  * @arg func            callback function
00526  * @arg arg             argument to be passed to callback function
00527  */
00528 int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind,
00529               nl_recvmsg_err_cb_t func, void *arg)
00530 {
00531         if (kind < 0 || kind > NL_CB_KIND_MAX)
00532                 return nl_error(ERANGE, "Callback kind out of range");
00533 
00534         if (kind == NL_CB_CUSTOM) {
00535                 cb->cb_err = func;
00536                 cb->cb_err_arg = arg;
00537         } else {
00538                 cb->cb_err = cb_err_def[kind];
00539                 cb->cb_err_arg = arg;
00540         }
00541 
00542         return 0;
00543 }
00544 
00545 /**
00546  * Overwrite internal calls to nl_recvmsgs()
00547  * @arg cb              callback configuration
00548  * @arg func            replacement callback for nl_recvmsgs()
00549  */
00550 void nl_cb_overwrite_recvmsgs(struct nl_cb *cb,
00551                               int (*func)(struct nl_handle *, struct nl_cb *))
00552 {
00553         cb->cb_recvmsgs_ow = func;
00554 }
00555 
00556 /**
00557  * Overwrite internal calls to nl_recv()
00558  * @arg cb              callback configuration
00559  * @arg func            replacement callback for nl_recv()
00560  */
00561 void nl_cb_overwrite_recv(struct nl_cb *cb,
00562                           int (*func)(struct nl_handle *, struct sockaddr_nl *,
00563                                       unsigned char **, struct ucred **))
00564 {
00565         cb->cb_recv_ow = func;
00566 }
00567 
00568 /**
00569  * Overwrite internal calls to nl_send()
00570  * @arg cb              callback configuration
00571  * @arg func            replacement callback for nl_send()
00572  */
00573 void nl_cb_overwrite_send(struct nl_cb *cb,
00574                           int (*func)(struct nl_handle *, struct nl_msg *))
00575 {
00576         cb->cb_send_ow = func;
00577 }
00578 
00579 /** @} */
00580 
00581 /** @} */

Generated on Fri Apr 27 14:14:07 2007 for libnl by  doxygen 1.5.1