libnl
3.2.3
|
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 /** @} */