handlers.c revision 1155370f520cb64657e25153255cf7dc1424317f
144d362409d5469aed47d19e7908d19bd194493aThomas Graf/* 244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/handlers.c default netlink message handlers 344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 444d362409d5469aed47d19e7908d19bd194493aThomas Graf * This library is free software; you can redistribute it and/or 544d362409d5469aed47d19e7908d19bd194493aThomas Graf * modify it under the terms of the GNU Lesser General Public 644d362409d5469aed47d19e7908d19bd194493aThomas Graf * License as published by the Free Software Foundation version 2.1 744d362409d5469aed47d19e7908d19bd194493aThomas Graf * of the License. 844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 98a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1144d362409d5469aed47d19e7908d19bd194493aThomas Graf 1244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @ingroup nl 1444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup cb Callbacks/Customization 1544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @brief 1644d362409d5469aed47d19e7908d19bd194493aThomas Graf * 1744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Callbacks and overwriting capabilities are provided to take influence 1844d362409d5469aed47d19e7908d19bd194493aThomas Graf * in various control flows inside the library. All callbacks are packed 1944d362409d5469aed47d19e7908d19bd194493aThomas Graf * together in struct nl_cb which is then attached to a netlink socket or 2044d362409d5469aed47d19e7908d19bd194493aThomas Graf * passed on to the respective functions directly. 2144d362409d5469aed47d19e7908d19bd194493aThomas Graf * 2244d362409d5469aed47d19e7908d19bd194493aThomas Graf * Callbacks can control the flow of the underlying layer by returning 2344d362409d5469aed47d19e7908d19bd194493aThomas Graf * the appropriate error codes: 2444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 2544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Action ID | Description 2644d362409d5469aed47d19e7908d19bd194493aThomas Graf * -----------------+------------------------------------------------------- 2744d362409d5469aed47d19e7908d19bd194493aThomas Graf * NL_OK | Proceed with whatever comes next. 2844d362409d5469aed47d19e7908d19bd194493aThomas Graf * NL_SKIP | Skip message currently being processed and continue 2944d362409d5469aed47d19e7908d19bd194493aThomas Graf * | with next message. 3044d362409d5469aed47d19e7908d19bd194493aThomas Graf * NL_STOP | Stop parsing and discard all remaining messages in 3144d362409d5469aed47d19e7908d19bd194493aThomas Graf * | this set of messages. 3244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 3344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 3444d362409d5469aed47d19e7908d19bd194493aThomas Graf * All callbacks are optional and a default action is performed if no 3544d362409d5469aed47d19e7908d19bd194493aThomas Graf * application specific implementation is provided: 3644d362409d5469aed47d19e7908d19bd194493aThomas Graf * 3744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 3844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Callback ID | Default Return Value 3944d362409d5469aed47d19e7908d19bd194493aThomas Graf * ------------------+---------------------- 4044d362409d5469aed47d19e7908d19bd194493aThomas Graf * NL_CB_VALID | NL_OK 4144d362409d5469aed47d19e7908d19bd194493aThomas Graf * NL_CB_FINISH | NL_STOP 4244d362409d5469aed47d19e7908d19bd194493aThomas Graf * NL_CB_OVERRUN | NL_STOP 4344d362409d5469aed47d19e7908d19bd194493aThomas Graf * NL_CB_SKIPPED | NL_SKIP 4444d362409d5469aed47d19e7908d19bd194493aThomas Graf * NL_CB_ACK | NL_STOP 4544d362409d5469aed47d19e7908d19bd194493aThomas Graf * NL_CB_MSG_IN | NL_OK 4644d362409d5469aed47d19e7908d19bd194493aThomas Graf * NL_CB_MSG_OUT | NL_OK 4744d362409d5469aed47d19e7908d19bd194493aThomas Graf * NL_CB_INVALID | NL_STOP 4844d362409d5469aed47d19e7908d19bd194493aThomas Graf * NL_CB_SEQ_CHECK | NL_OK 4944d362409d5469aed47d19e7908d19bd194493aThomas Graf * NL_CB_SEND_ACK | NL_OK 5044d362409d5469aed47d19e7908d19bd194493aThomas Graf * | 5144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Error Callback | NL_STOP 5244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 5344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 5444d362409d5469aed47d19e7908d19bd194493aThomas Graf * In order to simplify typical usages of the library, different sets of 5544d362409d5469aed47d19e7908d19bd194493aThomas Graf * default callback implementations exist: 5644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 5744d362409d5469aed47d19e7908d19bd194493aThomas Graf * NL_CB_DEFAULT: No additional actions 5844d362409d5469aed47d19e7908d19bd194493aThomas Graf * NL_CB_VERBOSE: Automatically print warning and error messages to a file 5944d362409d5469aed47d19e7908d19bd194493aThomas Graf * descriptor as appropriate. This is useful for CLI based 6044d362409d5469aed47d19e7908d19bd194493aThomas Graf * applications. 6144d362409d5469aed47d19e7908d19bd194493aThomas Graf * NL_CB_DEBUG: Print informal debugging information for each message 6244d362409d5469aed47d19e7908d19bd194493aThomas Graf * received. This will result in every message beint sent or 6344d362409d5469aed47d19e7908d19bd194493aThomas Graf * received to be printed to the screen in a decoded, 6444d362409d5469aed47d19e7908d19bd194493aThomas Graf * human-readable format. 6544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 6644d362409d5469aed47d19e7908d19bd194493aThomas Graf * 6744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par 1) Setting up a callback set 6844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 6944d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Allocate a callback set and initialize it to the verbose default set 7044d362409d5469aed47d19e7908d19bd194493aThomas Graf * struct nl_cb *cb = nl_cb_alloc(NL_CB_VERBOSE); 7144d362409d5469aed47d19e7908d19bd194493aThomas Graf * 7244d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Modify the set to call my_func() for all valid messages 7344d362409d5469aed47d19e7908d19bd194493aThomas Graf * nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL); 7444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 7544d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Set the error message handler to the verbose default implementation 7644d362409d5469aed47d19e7908d19bd194493aThomas Graf * // and direct it to print all errors to the given file descriptor. 7744d362409d5469aed47d19e7908d19bd194493aThomas Graf * FILE *file = fopen(...); 7844d362409d5469aed47d19e7908d19bd194493aThomas Graf * nl_cb_err(cb, NL_CB_VERBOSE, NULL, file); 7944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 8044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 8144d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 8244d362409d5469aed47d19e7908d19bd194493aThomas Graf 8344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-local.h> 8444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h> 8544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h> 8644d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/msg.h> 8744d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/handlers.h> 8844d362409d5469aed47d19e7908d19bd194493aThomas Graf 8944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void print_header_content(FILE *ofd, struct nlmsghdr *n) 9044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 9144d362409d5469aed47d19e7908d19bd194493aThomas Graf char flags[128]; 9244d362409d5469aed47d19e7908d19bd194493aThomas Graf char type[32]; 9344d362409d5469aed47d19e7908d19bd194493aThomas Graf 9444d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "type=%s length=%u flags=<%s> sequence-nr=%u pid=%u", 9544d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_nlmsgtype2str(n->nlmsg_type, type, sizeof(type)), 9644d362409d5469aed47d19e7908d19bd194493aThomas Graf n->nlmsg_len, nl_nlmsg_flags2str(n->nlmsg_flags, flags, 9744d362409d5469aed47d19e7908d19bd194493aThomas Graf sizeof(flags)), n->nlmsg_seq, n->nlmsg_pid); 9844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 9944d362409d5469aed47d19e7908d19bd194493aThomas Graf 10044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_valid_handler_verbose(struct nl_msg *msg, void *arg) 10144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 10244d362409d5469aed47d19e7908d19bd194493aThomas Graf FILE *ofd = arg ? arg : stdout; 10344d362409d5469aed47d19e7908d19bd194493aThomas Graf 10444d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "-- Warning: unhandled valid message: "); 10544d362409d5469aed47d19e7908d19bd194493aThomas Graf print_header_content(ofd, nlmsg_hdr(msg)); 10644d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "\n"); 10744d362409d5469aed47d19e7908d19bd194493aThomas Graf 10844d362409d5469aed47d19e7908d19bd194493aThomas Graf return NL_OK; 10944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 11044d362409d5469aed47d19e7908d19bd194493aThomas Graf 11144d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_invalid_handler_verbose(struct nl_msg *msg, void *arg) 11244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 11344d362409d5469aed47d19e7908d19bd194493aThomas Graf FILE *ofd = arg ? arg : stderr; 11444d362409d5469aed47d19e7908d19bd194493aThomas Graf 11544d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "-- Error: Invalid message: "); 11644d362409d5469aed47d19e7908d19bd194493aThomas Graf print_header_content(ofd, nlmsg_hdr(msg)); 11744d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "\n"); 11844d362409d5469aed47d19e7908d19bd194493aThomas Graf 11944d362409d5469aed47d19e7908d19bd194493aThomas Graf return NL_STOP; 12044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 12144d362409d5469aed47d19e7908d19bd194493aThomas Graf 12244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_overrun_handler_verbose(struct nl_msg *msg, void *arg) 12344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 12444d362409d5469aed47d19e7908d19bd194493aThomas Graf FILE *ofd = arg ? arg : stderr; 12544d362409d5469aed47d19e7908d19bd194493aThomas Graf 12644d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "-- Error: Netlink Overrun: "); 12744d362409d5469aed47d19e7908d19bd194493aThomas Graf print_header_content(ofd, nlmsg_hdr(msg)); 12844d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "\n"); 12944d362409d5469aed47d19e7908d19bd194493aThomas Graf 13044d362409d5469aed47d19e7908d19bd194493aThomas Graf return NL_STOP; 13144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 13244d362409d5469aed47d19e7908d19bd194493aThomas Graf 13344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_error_handler_verbose(struct sockaddr_nl *who, 13444d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlmsgerr *e, void *arg) 13544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 13644d362409d5469aed47d19e7908d19bd194493aThomas Graf FILE *ofd = arg ? arg : stderr; 13744d362409d5469aed47d19e7908d19bd194493aThomas Graf 13844d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "-- Error received: %s\n-- Original message: ", 13944d362409d5469aed47d19e7908d19bd194493aThomas Graf strerror(-e->error)); 14044d362409d5469aed47d19e7908d19bd194493aThomas Graf print_header_content(ofd, &e->msg); 14144d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "\n"); 14244d362409d5469aed47d19e7908d19bd194493aThomas Graf 1438a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -nl_syserr2nlerr(e->error); 14444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 14544d362409d5469aed47d19e7908d19bd194493aThomas Graf 14644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_valid_handler_debug(struct nl_msg *msg, void *arg) 14744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 14844d362409d5469aed47d19e7908d19bd194493aThomas Graf FILE *ofd = arg ? arg : stderr; 14944d362409d5469aed47d19e7908d19bd194493aThomas Graf 15044d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "-- Debug: Unhandled Valid message: "); 15144d362409d5469aed47d19e7908d19bd194493aThomas Graf print_header_content(ofd, nlmsg_hdr(msg)); 15244d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "\n"); 15344d362409d5469aed47d19e7908d19bd194493aThomas Graf 15444d362409d5469aed47d19e7908d19bd194493aThomas Graf return NL_OK; 15544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 15644d362409d5469aed47d19e7908d19bd194493aThomas Graf 15744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_finish_handler_debug(struct nl_msg *msg, void *arg) 15844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 15944d362409d5469aed47d19e7908d19bd194493aThomas Graf FILE *ofd = arg ? arg : stderr; 16044d362409d5469aed47d19e7908d19bd194493aThomas Graf 16144d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "-- Debug: End of multipart message block: "); 16244d362409d5469aed47d19e7908d19bd194493aThomas Graf print_header_content(ofd, nlmsg_hdr(msg)); 16344d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "\n"); 16444d362409d5469aed47d19e7908d19bd194493aThomas Graf 16544d362409d5469aed47d19e7908d19bd194493aThomas Graf return NL_STOP; 16644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 16744d362409d5469aed47d19e7908d19bd194493aThomas Graf 16844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_msg_in_handler_debug(struct nl_msg *msg, void *arg) 16944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 17044d362409d5469aed47d19e7908d19bd194493aThomas Graf FILE *ofd = arg ? arg : stderr; 17144d362409d5469aed47d19e7908d19bd194493aThomas Graf 17244d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "-- Debug: Received Message:\n"); 17344d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_msg_dump(msg, ofd); 17444d362409d5469aed47d19e7908d19bd194493aThomas Graf 17544d362409d5469aed47d19e7908d19bd194493aThomas Graf return NL_OK; 17644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 17744d362409d5469aed47d19e7908d19bd194493aThomas Graf 17844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_msg_out_handler_debug(struct nl_msg *msg, void *arg) 17944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 18044d362409d5469aed47d19e7908d19bd194493aThomas Graf FILE *ofd = arg ? arg : stderr; 18144d362409d5469aed47d19e7908d19bd194493aThomas Graf 18244d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "-- Debug: Sent Message:\n"); 18344d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_msg_dump(msg, ofd); 18444d362409d5469aed47d19e7908d19bd194493aThomas Graf 18544d362409d5469aed47d19e7908d19bd194493aThomas Graf return NL_OK; 18644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 18744d362409d5469aed47d19e7908d19bd194493aThomas Graf 18844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_skipped_handler_debug(struct nl_msg *msg, void *arg) 18944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 19044d362409d5469aed47d19e7908d19bd194493aThomas Graf FILE *ofd = arg ? arg : stderr; 19144d362409d5469aed47d19e7908d19bd194493aThomas Graf 19244d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "-- Debug: Skipped message: "); 19344d362409d5469aed47d19e7908d19bd194493aThomas Graf print_header_content(ofd, nlmsg_hdr(msg)); 19444d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "\n"); 19544d362409d5469aed47d19e7908d19bd194493aThomas Graf 19644d362409d5469aed47d19e7908d19bd194493aThomas Graf return NL_SKIP; 19744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 19844d362409d5469aed47d19e7908d19bd194493aThomas Graf 19944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_ack_handler_debug(struct nl_msg *msg, void *arg) 20044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 20144d362409d5469aed47d19e7908d19bd194493aThomas Graf FILE *ofd = arg ? arg : stderr; 20244d362409d5469aed47d19e7908d19bd194493aThomas Graf 20344d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "-- Debug: ACK: "); 20444d362409d5469aed47d19e7908d19bd194493aThomas Graf print_header_content(ofd, nlmsg_hdr(msg)); 20544d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "\n"); 20644d362409d5469aed47d19e7908d19bd194493aThomas Graf 20744d362409d5469aed47d19e7908d19bd194493aThomas Graf return NL_STOP; 20844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 20944d362409d5469aed47d19e7908d19bd194493aThomas Graf 21044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic nl_recvmsg_msg_cb_t cb_def[NL_CB_TYPE_MAX+1][NL_CB_KIND_MAX+1] = { 21144d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_VALID] = { 21244d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_VERBOSE] = nl_valid_handler_verbose, 21344d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_DEBUG] = nl_valid_handler_debug, 21444d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 21544d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_FINISH] = { 21644d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_DEBUG] = nl_finish_handler_debug, 21744d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 21844d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_INVALID] = { 21944d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_VERBOSE] = nl_invalid_handler_verbose, 22044d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_DEBUG] = nl_invalid_handler_verbose, 22144d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 22244d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_MSG_IN] = { 22344d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_DEBUG] = nl_msg_in_handler_debug, 22444d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 22544d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_MSG_OUT] = { 22644d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_DEBUG] = nl_msg_out_handler_debug, 22744d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 22844d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_OVERRUN] = { 22944d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_VERBOSE] = nl_overrun_handler_verbose, 23044d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_DEBUG] = nl_overrun_handler_verbose, 23144d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 23244d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_SKIPPED] = { 23344d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_DEBUG] = nl_skipped_handler_debug, 23444d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 23544d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_ACK] = { 23644d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_DEBUG] = nl_ack_handler_debug, 23744d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 23844d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 23944d362409d5469aed47d19e7908d19bd194493aThomas Graf 24044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic nl_recvmsg_err_cb_t cb_err_def[NL_CB_KIND_MAX+1] = { 24144d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_VERBOSE] = nl_error_handler_verbose, 24244d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_DEBUG] = nl_error_handler_verbose, 24344d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 24444d362409d5469aed47d19e7908d19bd194493aThomas Graf 24544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 24644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Callback Handle Management 24744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 24844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 24944d362409d5469aed47d19e7908d19bd194493aThomas Graf 25044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 25144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Allocate a new callback handle 25244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg kind callback kind to be used for initialization 25344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Newly allocated callback handle or NULL 25444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 25544d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_cb *nl_cb_alloc(enum nl_cb_kind kind) 25644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 25744d362409d5469aed47d19e7908d19bd194493aThomas Graf int i; 25844d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_cb *cb; 25944d362409d5469aed47d19e7908d19bd194493aThomas Graf 26044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (kind < 0 || kind > NL_CB_KIND_MAX) 26144d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 26244d362409d5469aed47d19e7908d19bd194493aThomas Graf 26344d362409d5469aed47d19e7908d19bd194493aThomas Graf cb = calloc(1, sizeof(*cb)); 2648a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if (!cb) 26544d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 26644d362409d5469aed47d19e7908d19bd194493aThomas Graf 26744d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_refcnt = 1; 26844d362409d5469aed47d19e7908d19bd194493aThomas Graf 26944d362409d5469aed47d19e7908d19bd194493aThomas Graf for (i = 0; i <= NL_CB_TYPE_MAX; i++) 27044d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_cb_set(cb, i, kind, NULL, NULL); 27144d362409d5469aed47d19e7908d19bd194493aThomas Graf 27244d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_cb_err(cb, kind, NULL, NULL); 27344d362409d5469aed47d19e7908d19bd194493aThomas Graf 27444d362409d5469aed47d19e7908d19bd194493aThomas Graf return cb; 27544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 27644d362409d5469aed47d19e7908d19bd194493aThomas Graf 27744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 27844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Clone an existing callback handle 27944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg orig original callback handle 28044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Newly allocated callback handle being a duplicate of 28144d362409d5469aed47d19e7908d19bd194493aThomas Graf * orig or NULL 28244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 28344d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_cb *nl_cb_clone(struct nl_cb *orig) 28444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 28544d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_cb *cb; 28644d362409d5469aed47d19e7908d19bd194493aThomas Graf 28744d362409d5469aed47d19e7908d19bd194493aThomas Graf cb = nl_cb_alloc(NL_CB_DEFAULT); 28844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!cb) 28944d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 29044d362409d5469aed47d19e7908d19bd194493aThomas Graf 29144d362409d5469aed47d19e7908d19bd194493aThomas Graf memcpy(cb, orig, sizeof(*orig)); 29244d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_refcnt = 1; 29344d362409d5469aed47d19e7908d19bd194493aThomas Graf 29444d362409d5469aed47d19e7908d19bd194493aThomas Graf return cb; 29544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 29644d362409d5469aed47d19e7908d19bd194493aThomas Graf 29744d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_cb *nl_cb_get(struct nl_cb *cb) 29844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 29944d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_refcnt++; 30044d362409d5469aed47d19e7908d19bd194493aThomas Graf 30144d362409d5469aed47d19e7908d19bd194493aThomas Graf return cb; 30244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 30344d362409d5469aed47d19e7908d19bd194493aThomas Graf 30444d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nl_cb_put(struct nl_cb *cb) 30544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 30644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!cb) 30744d362409d5469aed47d19e7908d19bd194493aThomas Graf return; 30844d362409d5469aed47d19e7908d19bd194493aThomas Graf 30944d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_refcnt--; 31044d362409d5469aed47d19e7908d19bd194493aThomas Graf 31144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (cb->cb_refcnt < 0) 31244d362409d5469aed47d19e7908d19bd194493aThomas Graf BUG(); 31344d362409d5469aed47d19e7908d19bd194493aThomas Graf 31444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (cb->cb_refcnt <= 0) 31544d362409d5469aed47d19e7908d19bd194493aThomas Graf free(cb); 31644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 31744d362409d5469aed47d19e7908d19bd194493aThomas Graf 31844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 31944d362409d5469aed47d19e7908d19bd194493aThomas Graf 32044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 32144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Callback Setup 32244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 32344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 32444d362409d5469aed47d19e7908d19bd194493aThomas Graf 32544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 32644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Set up a callback 32744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cb callback set 32844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg type callback to modify 32944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg kind kind of implementation 33044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg func callback function (NL_CB_CUSTOM) 33144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg arg argument passed to callback 33244d362409d5469aed47d19e7908d19bd194493aThomas Graf * 33344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code 33444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 33544d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind, 33644d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_recvmsg_msg_cb_t func, void *arg) 33744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 33844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (type < 0 || type > NL_CB_TYPE_MAX) 3398a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_RANGE; 34044d362409d5469aed47d19e7908d19bd194493aThomas Graf 34144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (kind < 0 || kind > NL_CB_KIND_MAX) 3428a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_RANGE; 34344d362409d5469aed47d19e7908d19bd194493aThomas Graf 34444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (kind == NL_CB_CUSTOM) { 34544d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_set[type] = func; 34644d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_args[type] = arg; 34744d362409d5469aed47d19e7908d19bd194493aThomas Graf } else { 34844d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_set[type] = cb_def[type][kind]; 34944d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_args[type] = arg; 35044d362409d5469aed47d19e7908d19bd194493aThomas Graf } 35144d362409d5469aed47d19e7908d19bd194493aThomas Graf 35244d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 35344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 35444d362409d5469aed47d19e7908d19bd194493aThomas Graf 35544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 35644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Set up a all callbacks 35744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cb callback set 35844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg kind kind of callback 35944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg func callback function 36044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg arg argument to be passwd to callback function 36144d362409d5469aed47d19e7908d19bd194493aThomas Graf * 36244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code 36344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 36444d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind, 36544d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_recvmsg_msg_cb_t func, void *arg) 36644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 36744d362409d5469aed47d19e7908d19bd194493aThomas Graf int i, err; 36844d362409d5469aed47d19e7908d19bd194493aThomas Graf 36944d362409d5469aed47d19e7908d19bd194493aThomas Graf for (i = 0; i <= NL_CB_TYPE_MAX; i++) { 37044d362409d5469aed47d19e7908d19bd194493aThomas Graf err = nl_cb_set(cb, i, kind, func, arg); 37144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 37244d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 37344d362409d5469aed47d19e7908d19bd194493aThomas Graf } 37444d362409d5469aed47d19e7908d19bd194493aThomas Graf 37544d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 37644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 37744d362409d5469aed47d19e7908d19bd194493aThomas Graf 37844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 37944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Set up an error callback 38044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cb callback set 38144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg kind kind of callback 38244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg func callback function 38344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg arg argument to be passed to callback function 38444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 38544d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind, 38644d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_recvmsg_err_cb_t func, void *arg) 38744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 38844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (kind < 0 || kind > NL_CB_KIND_MAX) 3898a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_RANGE; 39044d362409d5469aed47d19e7908d19bd194493aThomas Graf 39144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (kind == NL_CB_CUSTOM) { 39244d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_err = func; 39344d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_err_arg = arg; 39444d362409d5469aed47d19e7908d19bd194493aThomas Graf } else { 39544d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_err = cb_err_def[kind]; 39644d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_err_arg = arg; 39744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 39844d362409d5469aed47d19e7908d19bd194493aThomas Graf 39944d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 40044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 40144d362409d5469aed47d19e7908d19bd194493aThomas Graf 40244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 40344d362409d5469aed47d19e7908d19bd194493aThomas Graf 40444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 40544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Overwriting 40644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 40744d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 40844d362409d5469aed47d19e7908d19bd194493aThomas Graf 40944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 41044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Overwrite internal calls to nl_recvmsgs() 41144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cb callback set 41244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg func replacement callback for nl_recvmsgs() 41344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 41444d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nl_cb_overwrite_recvmsgs(struct nl_cb *cb, 4151155370f520cb64657e25153255cf7dc1424317fThomas Graf int (*func)(struct nl_sock *, struct nl_cb *)) 41644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 41744d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_recvmsgs_ow = func; 41844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 41944d362409d5469aed47d19e7908d19bd194493aThomas Graf 42044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 42144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Overwrite internal calls to nl_recv() 42244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cb callback set 42344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg func replacement callback for nl_recv() 42444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 42544d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nl_cb_overwrite_recv(struct nl_cb *cb, 4261155370f520cb64657e25153255cf7dc1424317fThomas Graf int (*func)(struct nl_sock *, struct sockaddr_nl *, 42744d362409d5469aed47d19e7908d19bd194493aThomas Graf unsigned char **, struct ucred **)) 42844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 42944d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_recv_ow = func; 43044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 43144d362409d5469aed47d19e7908d19bd194493aThomas Graf 43244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 43344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Overwrite internal calls to nl_send() 43444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cb callback set 43544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg func replacement callback for nl_send() 43644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 43744d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nl_cb_overwrite_send(struct nl_cb *cb, 4381155370f520cb64657e25153255cf7dc1424317fThomas Graf int (*func)(struct nl_sock *, struct nl_msg *)) 43944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 44044d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_send_ow = func; 44144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 44244d362409d5469aed47d19e7908d19bd194493aThomas Graf 44344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 44444d362409d5469aed47d19e7908d19bd194493aThomas Graf 44544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 446