OpenWrt – Rev 1
?pathlinks?
/*
* netlink/handlers.c default netlink message handlers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_HANDLERS_H_
#define NETLINK_HANDLERS_H_
#include <stdio.h>
#include <stdint.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netlink/netlink-compat.h>
#include <netlink/netlink-kernel.h>
#include <netlink/types.h>
#ifdef __cplusplus
extern "C" {
#endif
struct nl_sock;
struct nl_msg;
struct nl_cb;
/**
* @name Callback Typedefs
* @{
*/
/**
* nl_recvmsgs() callback for message processing customization
* @ingroup cb
* @arg msg netlink message being processed
* @arg arg argument passwd on through caller
*/
typedef int (*nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg);
/**
* nl_recvmsgs() callback for error message processing customization
* @ingroup cb
* @arg nla netlink address of the peer
* @arg nlerr netlink error message being processed
* @arg arg argument passed on through caller
*/
typedef int (*nl_recvmsg_err_cb_t)(struct sockaddr_nl *nla,
struct nlmsgerr *nlerr, void *arg);
/** @} */
/**
* Callback actions
* @ingroup cb
*/
enum nl_cb_action {
/** Proceed with wathever would come next */
NL_OK,
/** Skip this message */
NL_SKIP,
/** Stop parsing altogether and discard remaining messages */
NL_STOP,
};
/**
* Callback kinds
* @ingroup cb
*/
enum nl_cb_kind {
/** Default handlers (quiet) */
NL_CB_DEFAULT,
/** Verbose default handlers (error messages printed) */
NL_CB_VERBOSE,
/** Debug handlers for debugging */
NL_CB_DEBUG,
/** Customized handler specified by the user */
NL_CB_CUSTOM,
__NL_CB_KIND_MAX,
};
#define NL_CB_KIND_MAX (__NL_CB_KIND_MAX - 1)
/**
* Callback types
* @ingroup cb
*/
enum nl_cb_type {
/** Message is valid */
NL_CB_VALID,
/** Last message in a series of multi part messages received */
NL_CB_FINISH,
/** Report received that data was lost */
NL_CB_OVERRUN,
/** Message wants to be skipped */
NL_CB_SKIPPED,
/** Message is an acknowledge */
NL_CB_ACK,
/** Called for every message received */
NL_CB_MSG_IN,
/** Called for every message sent out except for nl_sendto() */
NL_CB_MSG_OUT,
/** Message is malformed and invalid */
NL_CB_INVALID,
/** Called instead of internal sequence number checking */
NL_CB_SEQ_CHECK,
/** Sending of an acknowledge message has been requested */
NL_CB_SEND_ACK,
__NL_CB_TYPE_MAX,
};
#define NL_CB_TYPE_MAX (__NL_CB_TYPE_MAX - 1)
struct nl_cb
{
nl_recvmsg_msg_cb_t cb_set[NL_CB_TYPE_MAX+1];
void * cb_args[NL_CB_TYPE_MAX+1];
nl_recvmsg_err_cb_t cb_err;
void * cb_err_arg;
/** May be used to replace nl_recvmsgs with your own implementation
* in all internal calls to nl_recvmsgs. */
int (*cb_recvmsgs_ow)(struct nl_sock *,
struct nl_cb *);
/** Overwrite internal calls to nl_recv, must return the number of
* octets read and allocate a buffer for the received data. */
int (*cb_recv_ow)(struct nl_sock *,
struct sockaddr_nl *,
unsigned char **,
struct ucred **);
/** Overwrites internal calls to nl_send, must send the netlink
* message. */
int (*cb_send_ow)(struct nl_sock *,
struct nl_msg *);
int cb_refcnt;
};
extern struct nl_cb * nl_cb_alloc(enum nl_cb_kind);
extern struct nl_cb * nl_cb_clone(struct nl_cb *);
extern void nl_cb_put(struct nl_cb *);
extern int nl_cb_set(struct nl_cb *, enum nl_cb_type, enum nl_cb_kind,
nl_recvmsg_msg_cb_t, void *);
extern int nl_cb_err(struct nl_cb *, enum nl_cb_kind, nl_recvmsg_err_cb_t,
void *);
static inline struct nl_cb *nl_cb_get(struct nl_cb *cb)
{
cb->cb_refcnt++;
return cb;
}
/**
* Set up a all callbacks
* @arg cb callback set
* @arg kind kind of callback
* @arg func callback function
* @arg arg argument to be passwd to callback function
*
* @return 0 on success or a negative error code
*/
static inline int nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind,
nl_recvmsg_msg_cb_t func, void *arg)
{
int i, err;
for (i = 0; i <= NL_CB_TYPE_MAX; i++) {
err = nl_cb_set(cb,(enum nl_cb_type)i, kind, func, arg);
if (err < 0)
return err;
}
return 0;
}
/**
* @name Overwriting
* @{
*/
/**
* Overwrite internal calls to nl_recvmsgs()
* @arg cb callback set
* @arg func replacement callback for nl_recvmsgs()
*/
static inline void nl_cb_overwrite_recvmsgs(struct nl_cb *cb,
int (*func)(struct nl_sock *, struct nl_cb *))
{
cb->cb_recvmsgs_ow = func;
}
/**
* Overwrite internal calls to nl_recv()
* @arg cb callback set
* @arg func replacement callback for nl_recv()
*/
static inline void nl_cb_overwrite_recv(struct nl_cb *cb,
int (*func)(struct nl_sock *, struct sockaddr_nl *,
unsigned char **, struct ucred **))
{
cb->cb_recv_ow = func;
}
/**
* Overwrite internal calls to nl_send()
* @arg cb callback set
* @arg func replacement callback for nl_send()
*/
static inline void nl_cb_overwrite_send(struct nl_cb *cb,
int (*func)(struct nl_sock *, struct nl_msg *))
{
cb->cb_send_ow = func;
}
/** @} */
#ifdef __cplusplus
}
#endif
#endif