Home | History | Annotate | Download | only in lib
      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 (at) suug.ch>
     10  */
     11 
     12 /**
     13  * @ingroup core
     14  * @defgroup cb Callbacks/Customization
     15  *
     16  * @details
     17  * @par 1) Setting up a callback set
     18  * @code
     19  * // Allocate a callback set and initialize it to the verbose default set
     20  * struct nl_cb *cb = nl_cb_alloc(NL_CB_VERBOSE);
     21  *
     22  * // Modify the set to call my_func() for all valid messages
     23  * nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL);
     24  *
     25  * // Set the error message handler to the verbose default implementation
     26  * // and direct it to print all errors to the given file descriptor.
     27  * FILE *file = fopen(...);
     28  * nl_cb_err(cb, NL_CB_VERBOSE, NULL, file);
     29  * @endcode
     30  * @{
     31  */
     32 
     33 #include <netlink-local.h>
     34 #include <netlink/netlink.h>
     35 #include <netlink/utils.h>
     36 #include <netlink/msg.h>
     37 #include <netlink/handlers.h>
     38 
     39 static void print_header_content(FILE *ofd, struct nlmsghdr *n)
     40 {
     41 	char flags[128];
     42 	char type[32];
     43 
     44 	fprintf(ofd, "type=%s length=%u flags=<%s> sequence-nr=%u pid=%u",
     45 		nl_nlmsgtype2str(n->nlmsg_type, type, sizeof(type)),
     46 		n->nlmsg_len, nl_nlmsg_flags2str(n->nlmsg_flags, flags,
     47 		sizeof(flags)), n->nlmsg_seq, n->nlmsg_pid);
     48 }
     49 
     50 static int nl_valid_handler_verbose(struct nl_msg *msg, void *arg)
     51 {
     52 	FILE *ofd = arg ? arg : stdout;
     53 
     54 	fprintf(ofd, "-- Warning: unhandled valid message: ");
     55 	print_header_content(ofd, nlmsg_hdr(msg));
     56 	fprintf(ofd, "\n");
     57 
     58 	return NL_OK;
     59 }
     60 
     61 static int nl_invalid_handler_verbose(struct nl_msg *msg, void *arg)
     62 {
     63 	FILE *ofd = arg ? arg : stderr;
     64 
     65 	fprintf(ofd, "-- Error: Invalid message: ");
     66 	print_header_content(ofd, nlmsg_hdr(msg));
     67 	fprintf(ofd, "\n");
     68 
     69 	return NL_STOP;
     70 }
     71 
     72 static int nl_overrun_handler_verbose(struct nl_msg *msg, void *arg)
     73 {
     74 	FILE *ofd = arg ? arg : stderr;
     75 
     76 	fprintf(ofd, "-- Error: Netlink Overrun: ");
     77 	print_header_content(ofd, nlmsg_hdr(msg));
     78 	fprintf(ofd, "\n");
     79 
     80 	return NL_STOP;
     81 }
     82 
     83 static int nl_error_handler_verbose(struct sockaddr_nl *who,
     84 				    struct nlmsgerr *e, void *arg)
     85 {
     86 	FILE *ofd = arg ? arg : stderr;
     87 
     88 	fprintf(ofd, "-- Error received: %s\n-- Original message: ",
     89 		strerror(-e->error));
     90 	print_header_content(ofd, &e->msg);
     91 	fprintf(ofd, "\n");
     92 
     93 	return -nl_syserr2nlerr(e->error);
     94 }
     95 
     96 static int nl_valid_handler_debug(struct nl_msg *msg, void *arg)
     97 {
     98 	FILE *ofd = arg ? arg : stderr;
     99 
    100 	fprintf(ofd, "-- Debug: Unhandled Valid message: ");
    101 	print_header_content(ofd, nlmsg_hdr(msg));
    102 	fprintf(ofd, "\n");
    103 
    104 	return NL_OK;
    105 }
    106 
    107 static int nl_finish_handler_debug(struct nl_msg *msg, void *arg)
    108 {
    109 	FILE *ofd = arg ? arg : stderr;
    110 
    111 	fprintf(ofd, "-- Debug: End of multipart message block: ");
    112 	print_header_content(ofd, nlmsg_hdr(msg));
    113 	fprintf(ofd, "\n");
    114 
    115 	return NL_STOP;
    116 }
    117 
    118 static int nl_msg_in_handler_debug(struct nl_msg *msg, void *arg)
    119 {
    120 	FILE *ofd = arg ? arg : stderr;
    121 
    122 	fprintf(ofd, "-- Debug: Received Message:\n");
    123 	nl_msg_dump(msg, ofd);
    124 
    125 	return NL_OK;
    126 }
    127 
    128 static int nl_msg_out_handler_debug(struct nl_msg *msg, void *arg)
    129 {
    130 	FILE *ofd = arg ? arg : stderr;
    131 
    132 	fprintf(ofd, "-- Debug: Sent Message:\n");
    133 	nl_msg_dump(msg, ofd);
    134 
    135 	return NL_OK;
    136 }
    137 
    138 static int nl_skipped_handler_debug(struct nl_msg *msg, void *arg)
    139 {
    140 	FILE *ofd = arg ? arg : stderr;
    141 
    142 	fprintf(ofd, "-- Debug: Skipped message: ");
    143 	print_header_content(ofd, nlmsg_hdr(msg));
    144 	fprintf(ofd, "\n");
    145 
    146 	return NL_SKIP;
    147 }
    148 
    149 static int nl_ack_handler_debug(struct nl_msg *msg, void *arg)
    150 {
    151 	FILE *ofd = arg ? arg : stderr;
    152 
    153 	fprintf(ofd, "-- Debug: ACK: ");
    154 	print_header_content(ofd, nlmsg_hdr(msg));
    155 	fprintf(ofd, "\n");
    156 
    157 	return NL_STOP;
    158 }
    159 
    160 static nl_recvmsg_msg_cb_t cb_def[NL_CB_TYPE_MAX+1][NL_CB_KIND_MAX+1] = {
    161 	[NL_CB_VALID] = {
    162 		[NL_CB_VERBOSE]	= nl_valid_handler_verbose,
    163 		[NL_CB_DEBUG]	= nl_valid_handler_debug,
    164 	},
    165 	[NL_CB_FINISH] = {
    166 		[NL_CB_DEBUG]	= nl_finish_handler_debug,
    167 	},
    168 	[NL_CB_INVALID] = {
    169 		[NL_CB_VERBOSE]	= nl_invalid_handler_verbose,
    170 		[NL_CB_DEBUG]	= nl_invalid_handler_verbose,
    171 	},
    172 	[NL_CB_MSG_IN] = {
    173 		[NL_CB_DEBUG]	= nl_msg_in_handler_debug,
    174 	},
    175 	[NL_CB_MSG_OUT] = {
    176 		[NL_CB_DEBUG]	= nl_msg_out_handler_debug,
    177 	},
    178 	[NL_CB_OVERRUN] = {
    179 		[NL_CB_VERBOSE]	= nl_overrun_handler_verbose,
    180 		[NL_CB_DEBUG]	= nl_overrun_handler_verbose,
    181 	},
    182 	[NL_CB_SKIPPED] = {
    183 		[NL_CB_DEBUG]	= nl_skipped_handler_debug,
    184 	},
    185 	[NL_CB_ACK] = {
    186 		[NL_CB_DEBUG]	= nl_ack_handler_debug,
    187 	},
    188 };
    189 
    190 static nl_recvmsg_err_cb_t cb_err_def[NL_CB_KIND_MAX+1] = {
    191 	[NL_CB_VERBOSE]	= nl_error_handler_verbose,
    192 	[NL_CB_DEBUG]	= nl_error_handler_verbose,
    193 };
    194 
    195 /**
    196  * @name Callback Handle Management
    197  * @{
    198  */
    199 
    200 /**
    201  * Allocate a new callback handle
    202  * @arg kind		callback kind to be used for initialization
    203  * @return Newly allocated callback handle or NULL
    204  */
    205 struct nl_cb *nl_cb_alloc(enum nl_cb_kind kind)
    206 {
    207 	int i;
    208 	struct nl_cb *cb;
    209 
    210 	if (kind < 0 || kind > NL_CB_KIND_MAX)
    211 		return NULL;
    212 
    213 	cb = calloc(1, sizeof(*cb));
    214 	if (!cb)
    215 		return NULL;
    216 
    217 	cb->cb_refcnt = 1;
    218 
    219 	for (i = 0; i <= NL_CB_TYPE_MAX; i++)
    220 		nl_cb_set(cb, i, kind, NULL, NULL);
    221 
    222 	nl_cb_err(cb, kind, NULL, NULL);
    223 
    224 	return cb;
    225 }
    226 
    227 /**
    228  * Clone an existing callback handle
    229  * @arg orig		original callback handle
    230  * @return Newly allocated callback handle being a duplicate of
    231  *         orig or NULL
    232  */
    233 struct nl_cb *nl_cb_clone(struct nl_cb *orig)
    234 {
    235 	struct nl_cb *cb;
    236 
    237 	cb = nl_cb_alloc(NL_CB_DEFAULT);
    238 	if (!cb)
    239 		return NULL;
    240 
    241 	memcpy(cb, orig, sizeof(*orig));
    242 	cb->cb_refcnt = 1;
    243 
    244 	return cb;
    245 }
    246 
    247 struct nl_cb *nl_cb_get(struct nl_cb *cb)
    248 {
    249 	cb->cb_refcnt++;
    250 
    251 	return cb;
    252 }
    253 
    254 void nl_cb_put(struct nl_cb *cb)
    255 {
    256 	if (!cb)
    257 		return;
    258 
    259 	cb->cb_refcnt--;
    260 
    261 	if (cb->cb_refcnt < 0)
    262 		BUG();
    263 
    264 	if (cb->cb_refcnt <= 0)
    265 		free(cb);
    266 }
    267 
    268 /** @} */
    269 
    270 /**
    271  * @name Callback Setup
    272  * @{
    273  */
    274 
    275 /**
    276  * Set up a callback
    277  * @arg cb		callback set
    278  * @arg type		callback to modify
    279  * @arg kind		kind of implementation
    280  * @arg func		callback function (NL_CB_CUSTOM)
    281  * @arg arg		argument passed to callback
    282  *
    283  * @return 0 on success or a negative error code
    284  */
    285 int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind,
    286 	      nl_recvmsg_msg_cb_t func, void *arg)
    287 {
    288 	if (type < 0 || type > NL_CB_TYPE_MAX)
    289 		return -NLE_RANGE;
    290 
    291 	if (kind < 0 || kind > NL_CB_KIND_MAX)
    292 		return -NLE_RANGE;
    293 
    294 	if (kind == NL_CB_CUSTOM) {
    295 		cb->cb_set[type] = func;
    296 		cb->cb_args[type] = arg;
    297 	} else {
    298 		cb->cb_set[type] = cb_def[type][kind];
    299 		cb->cb_args[type] = arg;
    300 	}
    301 
    302 	return 0;
    303 }
    304 
    305 /**
    306  * Set up a all callbacks
    307  * @arg cb		callback set
    308  * @arg kind		kind of callback
    309  * @arg func		callback function
    310  * @arg arg		argument to be passwd to callback function
    311  *
    312  * @return 0 on success or a negative error code
    313  */
    314 int nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind,
    315 		  nl_recvmsg_msg_cb_t func, void *arg)
    316 {
    317 	int i, err;
    318 
    319 	for (i = 0; i <= NL_CB_TYPE_MAX; i++) {
    320 		err = nl_cb_set(cb, i, kind, func, arg);
    321 		if (err < 0)
    322 			return err;
    323 	}
    324 
    325 	return 0;
    326 }
    327 
    328 /**
    329  * Set up an error callback
    330  * @arg cb		callback set
    331  * @arg kind		kind of callback
    332  * @arg func		callback function
    333  * @arg arg		argument to be passed to callback function
    334  */
    335 int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind,
    336 	      nl_recvmsg_err_cb_t func, void *arg)
    337 {
    338 	if (kind < 0 || kind > NL_CB_KIND_MAX)
    339 		return -NLE_RANGE;
    340 
    341 	if (kind == NL_CB_CUSTOM) {
    342 		cb->cb_err = func;
    343 		cb->cb_err_arg = arg;
    344 	} else {
    345 		cb->cb_err = cb_err_def[kind];
    346 		cb->cb_err_arg = arg;
    347 	}
    348 
    349 	return 0;
    350 }
    351 
    352 /** @} */
    353 
    354 /**
    355  * @name Overwriting
    356  * @{
    357  */
    358 
    359 /**
    360  * Overwrite internal calls to nl_recvmsgs()
    361  * @arg cb		callback set
    362  * @arg func		replacement callback for nl_recvmsgs()
    363  */
    364 void nl_cb_overwrite_recvmsgs(struct nl_cb *cb,
    365 			      int (*func)(struct nl_sock *, struct nl_cb *))
    366 {
    367 	cb->cb_recvmsgs_ow = func;
    368 }
    369 
    370 /**
    371  * Overwrite internal calls to nl_recv()
    372  * @arg cb		callback set
    373  * @arg func		replacement callback for nl_recv()
    374  */
    375 void nl_cb_overwrite_recv(struct nl_cb *cb,
    376 			  int (*func)(struct nl_sock *, struct sockaddr_nl *,
    377 				      unsigned char **, struct ucred **))
    378 {
    379 	cb->cb_recv_ow = func;
    380 }
    381 
    382 /**
    383  * Overwrite internal calls to nl_send()
    384  * @arg cb		callback set
    385  * @arg func		replacement callback for nl_send()
    386  */
    387 void nl_cb_overwrite_send(struct nl_cb *cb,
    388 			  int (*func)(struct nl_sock *, struct nl_msg *))
    389 {
    390 	cb->cb_send_ow = func;
    391 }
    392 
    393 /** @} */
    394 
    395 /** @} */
    396