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