handlers.c revision 6782b6f709d03877a5661a4c8d8f8bd1b461f43f
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/** 136782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf * @ingroup core 1444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup cb Callbacks/Customization 1544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 164fd5f7cb6627a22bd9f228b4259d5106ae39d535Thomas Graf * @details 1744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par 1) Setting up a callback set 1844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 1944d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Allocate a callback set and initialize it to the verbose default set 2044d362409d5469aed47d19e7908d19bd194493aThomas Graf * struct nl_cb *cb = nl_cb_alloc(NL_CB_VERBOSE); 2144d362409d5469aed47d19e7908d19bd194493aThomas Graf * 2244d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Modify the set to call my_func() for all valid messages 2344d362409d5469aed47d19e7908d19bd194493aThomas Graf * nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL); 2444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 2544d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Set the error message handler to the verbose default implementation 2644d362409d5469aed47d19e7908d19bd194493aThomas Graf * // and direct it to print all errors to the given file descriptor. 2744d362409d5469aed47d19e7908d19bd194493aThomas Graf * FILE *file = fopen(...); 2844d362409d5469aed47d19e7908d19bd194493aThomas Graf * nl_cb_err(cb, NL_CB_VERBOSE, NULL, file); 2944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 3044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 3144d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 3244d362409d5469aed47d19e7908d19bd194493aThomas Graf 3344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-local.h> 3444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h> 3544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h> 3644d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/msg.h> 3744d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/handlers.h> 3844d362409d5469aed47d19e7908d19bd194493aThomas Graf 3944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void print_header_content(FILE *ofd, struct nlmsghdr *n) 4044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 4144d362409d5469aed47d19e7908d19bd194493aThomas Graf char flags[128]; 4244d362409d5469aed47d19e7908d19bd194493aThomas Graf char type[32]; 4344d362409d5469aed47d19e7908d19bd194493aThomas Graf 4444d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "type=%s length=%u flags=<%s> sequence-nr=%u pid=%u", 4544d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_nlmsgtype2str(n->nlmsg_type, type, sizeof(type)), 4644d362409d5469aed47d19e7908d19bd194493aThomas Graf n->nlmsg_len, nl_nlmsg_flags2str(n->nlmsg_flags, flags, 4744d362409d5469aed47d19e7908d19bd194493aThomas Graf sizeof(flags)), n->nlmsg_seq, n->nlmsg_pid); 4844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 4944d362409d5469aed47d19e7908d19bd194493aThomas Graf 5044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_valid_handler_verbose(struct nl_msg *msg, void *arg) 5144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 5244d362409d5469aed47d19e7908d19bd194493aThomas Graf FILE *ofd = arg ? arg : stdout; 5344d362409d5469aed47d19e7908d19bd194493aThomas Graf 5444d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "-- Warning: unhandled valid message: "); 5544d362409d5469aed47d19e7908d19bd194493aThomas Graf print_header_content(ofd, nlmsg_hdr(msg)); 5644d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "\n"); 5744d362409d5469aed47d19e7908d19bd194493aThomas Graf 5844d362409d5469aed47d19e7908d19bd194493aThomas Graf return NL_OK; 5944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 6044d362409d5469aed47d19e7908d19bd194493aThomas Graf 6144d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_invalid_handler_verbose(struct nl_msg *msg, void *arg) 6244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 6344d362409d5469aed47d19e7908d19bd194493aThomas Graf FILE *ofd = arg ? arg : stderr; 6444d362409d5469aed47d19e7908d19bd194493aThomas Graf 6544d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "-- Error: Invalid message: "); 6644d362409d5469aed47d19e7908d19bd194493aThomas Graf print_header_content(ofd, nlmsg_hdr(msg)); 6744d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "\n"); 6844d362409d5469aed47d19e7908d19bd194493aThomas Graf 6944d362409d5469aed47d19e7908d19bd194493aThomas Graf return NL_STOP; 7044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 7144d362409d5469aed47d19e7908d19bd194493aThomas Graf 7244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_overrun_handler_verbose(struct nl_msg *msg, void *arg) 7344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 7444d362409d5469aed47d19e7908d19bd194493aThomas Graf FILE *ofd = arg ? arg : stderr; 7544d362409d5469aed47d19e7908d19bd194493aThomas Graf 7644d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "-- Error: Netlink Overrun: "); 7744d362409d5469aed47d19e7908d19bd194493aThomas Graf print_header_content(ofd, nlmsg_hdr(msg)); 7844d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "\n"); 7944d362409d5469aed47d19e7908d19bd194493aThomas Graf 8044d362409d5469aed47d19e7908d19bd194493aThomas Graf return NL_STOP; 8144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 8244d362409d5469aed47d19e7908d19bd194493aThomas Graf 8344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_error_handler_verbose(struct sockaddr_nl *who, 8444d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlmsgerr *e, void *arg) 8544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 8644d362409d5469aed47d19e7908d19bd194493aThomas Graf FILE *ofd = arg ? arg : stderr; 8744d362409d5469aed47d19e7908d19bd194493aThomas Graf 8844d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "-- Error received: %s\n-- Original message: ", 8944d362409d5469aed47d19e7908d19bd194493aThomas Graf strerror(-e->error)); 9044d362409d5469aed47d19e7908d19bd194493aThomas Graf print_header_content(ofd, &e->msg); 9144d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "\n"); 9244d362409d5469aed47d19e7908d19bd194493aThomas Graf 938a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -nl_syserr2nlerr(e->error); 9444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 9544d362409d5469aed47d19e7908d19bd194493aThomas Graf 9644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_valid_handler_debug(struct nl_msg *msg, void *arg) 9744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 9844d362409d5469aed47d19e7908d19bd194493aThomas Graf FILE *ofd = arg ? arg : stderr; 9944d362409d5469aed47d19e7908d19bd194493aThomas Graf 10044d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "-- Debug: Unhandled Valid message: "); 10144d362409d5469aed47d19e7908d19bd194493aThomas Graf print_header_content(ofd, nlmsg_hdr(msg)); 10244d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "\n"); 10344d362409d5469aed47d19e7908d19bd194493aThomas Graf 10444d362409d5469aed47d19e7908d19bd194493aThomas Graf return NL_OK; 10544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 10644d362409d5469aed47d19e7908d19bd194493aThomas Graf 10744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_finish_handler_debug(struct nl_msg *msg, void *arg) 10844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 10944d362409d5469aed47d19e7908d19bd194493aThomas Graf FILE *ofd = arg ? arg : stderr; 11044d362409d5469aed47d19e7908d19bd194493aThomas Graf 11144d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "-- Debug: End of multipart message block: "); 11244d362409d5469aed47d19e7908d19bd194493aThomas Graf print_header_content(ofd, nlmsg_hdr(msg)); 11344d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "\n"); 11444d362409d5469aed47d19e7908d19bd194493aThomas Graf 11544d362409d5469aed47d19e7908d19bd194493aThomas Graf return NL_STOP; 11644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 11744d362409d5469aed47d19e7908d19bd194493aThomas Graf 11844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_msg_in_handler_debug(struct nl_msg *msg, void *arg) 11944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 12044d362409d5469aed47d19e7908d19bd194493aThomas Graf FILE *ofd = arg ? arg : stderr; 12144d362409d5469aed47d19e7908d19bd194493aThomas Graf 12244d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "-- Debug: Received Message:\n"); 12344d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_msg_dump(msg, ofd); 12444d362409d5469aed47d19e7908d19bd194493aThomas Graf 12544d362409d5469aed47d19e7908d19bd194493aThomas Graf return NL_OK; 12644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 12744d362409d5469aed47d19e7908d19bd194493aThomas Graf 12844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_msg_out_handler_debug(struct nl_msg *msg, void *arg) 12944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 13044d362409d5469aed47d19e7908d19bd194493aThomas Graf FILE *ofd = arg ? arg : stderr; 13144d362409d5469aed47d19e7908d19bd194493aThomas Graf 13244d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "-- Debug: Sent Message:\n"); 13344d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_msg_dump(msg, ofd); 13444d362409d5469aed47d19e7908d19bd194493aThomas Graf 13544d362409d5469aed47d19e7908d19bd194493aThomas Graf return NL_OK; 13644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 13744d362409d5469aed47d19e7908d19bd194493aThomas Graf 13844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_skipped_handler_debug(struct nl_msg *msg, void *arg) 13944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 14044d362409d5469aed47d19e7908d19bd194493aThomas Graf FILE *ofd = arg ? arg : stderr; 14144d362409d5469aed47d19e7908d19bd194493aThomas Graf 14244d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "-- Debug: Skipped message: "); 14344d362409d5469aed47d19e7908d19bd194493aThomas Graf print_header_content(ofd, nlmsg_hdr(msg)); 14444d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "\n"); 14544d362409d5469aed47d19e7908d19bd194493aThomas Graf 14644d362409d5469aed47d19e7908d19bd194493aThomas Graf return NL_SKIP; 14744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 14844d362409d5469aed47d19e7908d19bd194493aThomas Graf 14944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nl_ack_handler_debug(struct nl_msg *msg, void *arg) 15044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 15144d362409d5469aed47d19e7908d19bd194493aThomas Graf FILE *ofd = arg ? arg : stderr; 15244d362409d5469aed47d19e7908d19bd194493aThomas Graf 15344d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "-- Debug: ACK: "); 15444d362409d5469aed47d19e7908d19bd194493aThomas Graf print_header_content(ofd, nlmsg_hdr(msg)); 15544d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(ofd, "\n"); 15644d362409d5469aed47d19e7908d19bd194493aThomas Graf 15744d362409d5469aed47d19e7908d19bd194493aThomas Graf return NL_STOP; 15844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 15944d362409d5469aed47d19e7908d19bd194493aThomas Graf 16044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic nl_recvmsg_msg_cb_t cb_def[NL_CB_TYPE_MAX+1][NL_CB_KIND_MAX+1] = { 16144d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_VALID] = { 16244d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_VERBOSE] = nl_valid_handler_verbose, 16344d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_DEBUG] = nl_valid_handler_debug, 16444d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 16544d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_FINISH] = { 16644d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_DEBUG] = nl_finish_handler_debug, 16744d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 16844d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_INVALID] = { 16944d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_VERBOSE] = nl_invalid_handler_verbose, 17044d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_DEBUG] = nl_invalid_handler_verbose, 17144d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 17244d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_MSG_IN] = { 17344d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_DEBUG] = nl_msg_in_handler_debug, 17444d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 17544d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_MSG_OUT] = { 17644d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_DEBUG] = nl_msg_out_handler_debug, 17744d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 17844d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_OVERRUN] = { 17944d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_VERBOSE] = nl_overrun_handler_verbose, 18044d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_DEBUG] = nl_overrun_handler_verbose, 18144d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 18244d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_SKIPPED] = { 18344d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_DEBUG] = nl_skipped_handler_debug, 18444d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 18544d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_ACK] = { 18644d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_DEBUG] = nl_ack_handler_debug, 18744d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 18844d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 18944d362409d5469aed47d19e7908d19bd194493aThomas Graf 19044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic nl_recvmsg_err_cb_t cb_err_def[NL_CB_KIND_MAX+1] = { 19144d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_VERBOSE] = nl_error_handler_verbose, 19244d362409d5469aed47d19e7908d19bd194493aThomas Graf [NL_CB_DEBUG] = nl_error_handler_verbose, 19344d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 19444d362409d5469aed47d19e7908d19bd194493aThomas Graf 19544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 19644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Callback Handle Management 19744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 19844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 19944d362409d5469aed47d19e7908d19bd194493aThomas Graf 20044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 20144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Allocate a new callback handle 20244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg kind callback kind to be used for initialization 20344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Newly allocated callback handle or NULL 20444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 20544d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_cb *nl_cb_alloc(enum nl_cb_kind kind) 20644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 20744d362409d5469aed47d19e7908d19bd194493aThomas Graf int i; 20844d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_cb *cb; 20944d362409d5469aed47d19e7908d19bd194493aThomas Graf 21044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (kind < 0 || kind > NL_CB_KIND_MAX) 21144d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 21244d362409d5469aed47d19e7908d19bd194493aThomas Graf 21344d362409d5469aed47d19e7908d19bd194493aThomas Graf cb = calloc(1, sizeof(*cb)); 2148a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if (!cb) 21544d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 21644d362409d5469aed47d19e7908d19bd194493aThomas Graf 21744d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_refcnt = 1; 21844d362409d5469aed47d19e7908d19bd194493aThomas Graf 21944d362409d5469aed47d19e7908d19bd194493aThomas Graf for (i = 0; i <= NL_CB_TYPE_MAX; i++) 22044d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_cb_set(cb, i, kind, NULL, NULL); 22144d362409d5469aed47d19e7908d19bd194493aThomas Graf 22244d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_cb_err(cb, kind, NULL, NULL); 22344d362409d5469aed47d19e7908d19bd194493aThomas Graf 22444d362409d5469aed47d19e7908d19bd194493aThomas Graf return cb; 22544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 22644d362409d5469aed47d19e7908d19bd194493aThomas Graf 22744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 22844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Clone an existing callback handle 22944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg orig original callback handle 23044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Newly allocated callback handle being a duplicate of 23144d362409d5469aed47d19e7908d19bd194493aThomas Graf * orig or NULL 23244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 23344d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_cb *nl_cb_clone(struct nl_cb *orig) 23444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 23544d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_cb *cb; 23644d362409d5469aed47d19e7908d19bd194493aThomas Graf 23744d362409d5469aed47d19e7908d19bd194493aThomas Graf cb = nl_cb_alloc(NL_CB_DEFAULT); 23844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!cb) 23944d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 24044d362409d5469aed47d19e7908d19bd194493aThomas Graf 24144d362409d5469aed47d19e7908d19bd194493aThomas Graf memcpy(cb, orig, sizeof(*orig)); 24244d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_refcnt = 1; 24344d362409d5469aed47d19e7908d19bd194493aThomas Graf 24444d362409d5469aed47d19e7908d19bd194493aThomas Graf return cb; 24544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 24644d362409d5469aed47d19e7908d19bd194493aThomas Graf 24744d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_cb *nl_cb_get(struct nl_cb *cb) 24844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 24944d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_refcnt++; 25044d362409d5469aed47d19e7908d19bd194493aThomas Graf 25144d362409d5469aed47d19e7908d19bd194493aThomas Graf return cb; 25244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 25344d362409d5469aed47d19e7908d19bd194493aThomas Graf 25444d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nl_cb_put(struct nl_cb *cb) 25544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 25644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!cb) 25744d362409d5469aed47d19e7908d19bd194493aThomas Graf return; 25844d362409d5469aed47d19e7908d19bd194493aThomas Graf 25944d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_refcnt--; 26044d362409d5469aed47d19e7908d19bd194493aThomas Graf 26144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (cb->cb_refcnt < 0) 26244d362409d5469aed47d19e7908d19bd194493aThomas Graf BUG(); 26344d362409d5469aed47d19e7908d19bd194493aThomas Graf 26444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (cb->cb_refcnt <= 0) 26544d362409d5469aed47d19e7908d19bd194493aThomas Graf free(cb); 26644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 26744d362409d5469aed47d19e7908d19bd194493aThomas Graf 26844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 26944d362409d5469aed47d19e7908d19bd194493aThomas Graf 27044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 27144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Callback Setup 27244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 27344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 27444d362409d5469aed47d19e7908d19bd194493aThomas Graf 27544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 27644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Set up a callback 27744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cb callback set 27844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg type callback to modify 27944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg kind kind of implementation 28044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg func callback function (NL_CB_CUSTOM) 28144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg arg argument passed to callback 28244d362409d5469aed47d19e7908d19bd194493aThomas Graf * 28344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code 28444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 28544d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind, 28644d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_recvmsg_msg_cb_t func, void *arg) 28744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 28844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (type < 0 || type > NL_CB_TYPE_MAX) 2898a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_RANGE; 29044d362409d5469aed47d19e7908d19bd194493aThomas Graf 29144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (kind < 0 || kind > NL_CB_KIND_MAX) 2928a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_RANGE; 29344d362409d5469aed47d19e7908d19bd194493aThomas Graf 29444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (kind == NL_CB_CUSTOM) { 29544d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_set[type] = func; 29644d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_args[type] = arg; 29744d362409d5469aed47d19e7908d19bd194493aThomas Graf } else { 29844d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_set[type] = cb_def[type][kind]; 29944d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_args[type] = arg; 30044d362409d5469aed47d19e7908d19bd194493aThomas Graf } 30144d362409d5469aed47d19e7908d19bd194493aThomas Graf 30244d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 30344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 30444d362409d5469aed47d19e7908d19bd194493aThomas Graf 30544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 30644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Set up a all callbacks 30744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cb callback set 30844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg kind kind of callback 30944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg func callback function 31044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg arg argument to be passwd to callback function 31144d362409d5469aed47d19e7908d19bd194493aThomas Graf * 31244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code 31344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 31444d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind, 31544d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_recvmsg_msg_cb_t func, void *arg) 31644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 31744d362409d5469aed47d19e7908d19bd194493aThomas Graf int i, err; 31844d362409d5469aed47d19e7908d19bd194493aThomas Graf 31944d362409d5469aed47d19e7908d19bd194493aThomas Graf for (i = 0; i <= NL_CB_TYPE_MAX; i++) { 32044d362409d5469aed47d19e7908d19bd194493aThomas Graf err = nl_cb_set(cb, i, kind, func, arg); 32144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 32244d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 32344d362409d5469aed47d19e7908d19bd194493aThomas Graf } 32444d362409d5469aed47d19e7908d19bd194493aThomas Graf 32544d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 32644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 32744d362409d5469aed47d19e7908d19bd194493aThomas Graf 32844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 32944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Set up an error callback 33044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cb callback set 33144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg kind kind of callback 33244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg func callback function 33344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg arg argument to be passed to callback function 33444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 33544d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind, 33644d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_recvmsg_err_cb_t func, void *arg) 33744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 33844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (kind < 0 || kind > NL_CB_KIND_MAX) 3398a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_RANGE; 34044d362409d5469aed47d19e7908d19bd194493aThomas Graf 34144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (kind == NL_CB_CUSTOM) { 34244d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_err = func; 34344d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_err_arg = arg; 34444d362409d5469aed47d19e7908d19bd194493aThomas Graf } else { 34544d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_err = cb_err_def[kind]; 34644d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_err_arg = arg; 34744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 34844d362409d5469aed47d19e7908d19bd194493aThomas Graf 34944d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 35044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 35144d362409d5469aed47d19e7908d19bd194493aThomas Graf 35244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 35344d362409d5469aed47d19e7908d19bd194493aThomas Graf 35444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 35544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Overwriting 35644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 35744d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 35844d362409d5469aed47d19e7908d19bd194493aThomas Graf 35944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 36044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Overwrite internal calls to nl_recvmsgs() 36144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cb callback set 36244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg func replacement callback for nl_recvmsgs() 36344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 36444d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nl_cb_overwrite_recvmsgs(struct nl_cb *cb, 3651155370f520cb64657e25153255cf7dc1424317fThomas Graf int (*func)(struct nl_sock *, struct nl_cb *)) 36644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 36744d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_recvmsgs_ow = func; 36844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 36944d362409d5469aed47d19e7908d19bd194493aThomas Graf 37044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 37144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Overwrite internal calls to nl_recv() 37244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cb callback set 37344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg func replacement callback for nl_recv() 37444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 37544d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nl_cb_overwrite_recv(struct nl_cb *cb, 3761155370f520cb64657e25153255cf7dc1424317fThomas Graf int (*func)(struct nl_sock *, struct sockaddr_nl *, 37744d362409d5469aed47d19e7908d19bd194493aThomas Graf unsigned char **, struct ucred **)) 37844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 37944d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_recv_ow = func; 38044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 38144d362409d5469aed47d19e7908d19bd194493aThomas Graf 38244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 38344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Overwrite internal calls to nl_send() 38444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cb callback set 38544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg func replacement callback for nl_send() 38644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 38744d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nl_cb_overwrite_send(struct nl_cb *cb, 3881155370f520cb64657e25153255cf7dc1424317fThomas Graf int (*func)(struct nl_sock *, struct nl_msg *)) 38944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 39044d362409d5469aed47d19e7908d19bd194493aThomas Graf cb->cb_send_ow = func; 39144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 39244d362409d5469aed47d19e7908d19bd194493aThomas Graf 39344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 39444d362409d5469aed47d19e7908d19bd194493aThomas Graf 39544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 396