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