genl: updates to API reference documentation

This commit is contained in:
Thomas Graf 2012-05-31 13:11:48 +02:00
parent d733f8a0a6
commit 0b70de5155
8 changed files with 486 additions and 265 deletions

View file

@ -6,7 +6,7 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
* Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_GENL_CTRL_H_

View file

@ -6,7 +6,7 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
* Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_GENL_FAMILY_H_
@ -25,25 +25,19 @@ extern struct genl_family * genl_family_alloc(void);
extern void genl_family_put(struct genl_family *);
extern unsigned int genl_family_get_id(struct genl_family *);
extern void genl_family_set_id(struct genl_family *,
unsigned int);
extern void genl_family_set_id(struct genl_family *, unsigned int);
extern char * genl_family_get_name(struct genl_family *);
extern void genl_family_set_name(struct genl_family *,
const char *name);
extern void genl_family_set_name(struct genl_family *, const char *);
extern uint8_t genl_family_get_version(struct genl_family *);
extern void genl_family_set_version(struct genl_family *,
uint8_t);
extern void genl_family_set_version(struct genl_family *, uint8_t);
extern uint32_t genl_family_get_hdrsize(struct genl_family *);
extern void genl_family_set_hdrsize(struct genl_family *,
uint32_t);
extern void genl_family_set_hdrsize(struct genl_family *, uint32_t);
extern uint32_t genl_family_get_maxattr(struct genl_family *);
extern void genl_family_set_maxattr(struct genl_family *,
uint32_t);
extern void genl_family_set_maxattr(struct genl_family *, uint32_t);
extern int genl_family_add_op(struct genl_family *,
int, int);
extern int genl_family_add_grp(struct genl_family *,
uint32_t , const char *);
extern int genl_family_add_op(struct genl_family *, int, int);
extern int genl_family_add_grp(struct genl_family *, uint32_t ,
const char *);
#ifdef __cplusplus

View file

@ -6,7 +6,7 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
* Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_GENL_H_
@ -32,6 +32,8 @@ extern int genlmsg_validate(struct nlmsghdr *, int, int,
struct nla_policy *);
extern int genlmsg_parse(struct nlmsghdr *, int, struct nlattr **,
int, struct nla_policy *);
extern struct genlmsghdr *
genlmsg_hdr(struct nlmsghdr *);
extern void * genlmsg_data(const struct genlmsghdr *);
extern int genlmsg_len(const struct genlmsghdr *);
extern struct nlattr * genlmsg_attrdata(const struct genlmsghdr *, int);

View file

@ -6,7 +6,7 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
* Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_GENL_MNGT_H_
@ -22,57 +22,124 @@ extern "C" {
struct nl_cache_ops;
/**
* @ingroup genl_mngt
* @struct genl_info netlink/genl/mngt.h
*
* Informative structure passed on to message parser callbacks
*
* This structure is passed on to all message parser callbacks and contains
* information about the sender of the message as well as pointers to all
* relevant sections of the parsed message.
*
* @see genl_cmd::c_msg_parser
*/
struct genl_info
{
/** Socket address of sender */
struct sockaddr_nl * who;
/** Pointer to Netlink message header */
struct nlmsghdr * nlh;
/** Pointer to Generic Netlink message header */
struct genlmsghdr * genlhdr;
/** Pointer to user header */
void * userhdr;
/** Pointer to array of parsed attributes */
struct nlattr ** attrs;
};
/**
* @ingroup genl_mngt
* Generic Netlink Command
* @struct genl_cmd netlink/genl/mngt.h
*
* Definition of a Generic Netlink command.
*
* This structure is used to define the list of available commands on the
* receiving side.
*
* @par Example:
* @code
* static struct genl_cmd foo_cmds[] = {
* {
* .c_id = FOO_CMD_NEW,
* .c_name = "NEWFOO" ,
* .c_maxattr = FOO_ATTR_MAX,
* .c_attr_policy = foo_policy,
* .c_msg_parser = foo_msg_parser,
* },
* {
* .c_id = FOO_CMD_DEL,
* .c_name = "DELFOO" ,
* },
* };
*
* static struct genl_ops my_genl_ops = {
* [...]
* .o_cmds = foo_cmds,
* .o_ncmds = ARRAY_SIZE(foo_cmds),
* };
* @endcode
*/
struct genl_cmd
{
/** Unique command identifier */
/** Numeric command identifier (required) */
int c_id;
/** Name/description of command */
/** Human readable name (required) */
char * c_name;
/**
* Maximum attribute identifier, must be provided if
* a message parser is available.
*/
/** Maximum attribute identifier that the command is prepared to handle. */
int c_maxattr;
/** Called whenever a message for this command is received */
int (*c_msg_parser)(struct nl_cache_ops *,
struct genl_cmd *,
struct genl_info *, void *);
/**
* Attribute validation policy (optional)
*/
/** Attribute validation policy, enforced before the callback is called */
struct nla_policy * c_attr_policy;
};
/**
* @ingroup genl_mngt
* Generic Netlink Operations
* @struct genl_ops netlink/genl/mngt.h
*
* Definition of a Generic Netlink family
*
* @see genl_cmd
*/
struct genl_ops
{
int o_family;
/** Numeric identifier, automatically resolved by genl_mngt_resolve() */
int o_id;
/** Human readable name, used to resolve to numeric identifier */
char * o_name;
/**
* If registered via genl_register(), will point to the related
* cache operations.
*/
struct nl_cache_ops * o_cache_ops;
/**
* Can point to an array of generic netlink commands definitions.
*/
struct genl_cmd * o_cmds;
/** Size of \c o_cmds array */
int o_ncmds;
/* linked list of all genl cache operations */
/**
* @private
* Used internally to link together all registered operations.
*/
struct nl_list_head o_list;
};

View file

@ -6,14 +6,18 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
* Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
*/
/**
* @ingroup genl_mngt
* @defgroup ctrl Controller
* @brief
* @ingroup genl
* @defgroup genl_ctrl Controller (Resolver)
*
* Resolves Generic Netlink family names to numeric identifiers.
*
* The controller is a component in the kernel that resolves Generic Netlink
* family names to their numeric identifiers. This module provides functions
* to query the controller to access the resolving functionality.
* @{
*/
@ -29,7 +33,6 @@
#define CTRL_VERSION 0x0001
static struct nl_cache_ops genl_ctrl_ops;
/** @endcond */
static int ctrl_request_update(struct nl_cache *c, struct nl_sock *h)
{
@ -173,27 +176,51 @@ errout:
return err;
}
/** @endcond */
/**
* @name Cache Management
* @name Controller Cache
*
* The controller cache allows to keep a local copy of the list of all
* kernel side registered Generic Netlink families to quickly resolve
* multiple Generic Netlink family names without requiring to communicate
* with the kernel for each resolving iteration.
*
* @{
*/
int genl_ctrl_alloc_cache(struct nl_sock *sock, struct nl_cache **result)
/**
* Allocate a new controller cache
* @arg sk Generic Netlink socket
* @arg result Pointer to store resulting cache
*
* Allocates a new cache mirroring the state of the controller and stores it
* in \c *result. The allocated cache will contain a list of all currently
* registered kernel side Generic Netlink families. The cache is meant to be
* used to resolve family names locally.
*
* @return 0 on success or a negative error code.
*/
int genl_ctrl_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
{
return nl_cache_alloc_and_fill(&genl_ctrl_ops, sock, result);
return nl_cache_alloc_and_fill(&genl_ctrl_ops, sk, result);
}
/**
* Look up generic netlink family by id in the provided cache.
* @arg cache Generic netlink family cache.
* @arg id Family identifier.
* Search controller cache for a numeric address match
* @arg cache Controller cache
* @arg id Numeric family identifier.
*
* Searches through the cache looking for a registered family
* matching the specified identifier. The caller will own a
* reference on the returned object which needs to be given
* back after usage using genl_family_put().
* Searches a previously allocated controller cache and looks for an entry
* that matches the specified numeric family identifier \c id. If a match
* is found successfully, the reference count of the matching object is
* increased by one before the objet is returned.
*
* @return Generic netlink family object or NULL if no match was found.
* @see genl_ctrl_alloc_cache()
* @see genl_ctrl_search_by_name()
* @see genl_family_put()
*
* @return Generic Netlink family object or NULL if no match was found.
*/
struct genl_family *genl_ctrl_search(struct nl_cache *cache, int id)
{
@ -213,24 +240,23 @@ struct genl_family *genl_ctrl_search(struct nl_cache *cache, int id)
}
/**
* @name Resolver
* @{
*/
/**
* Look up generic netlink family by family name in the provided cache.
* @arg cache Generic netlink family cache.
* @arg name Family name.
* Search controller cache for a family name match
* @arg cache Controller cache
* @arg name Name of Generic Netlink family
*
* Searches through the cache looking for a registered family
* matching the specified name. The caller will own a reference
* on the returned object which needs to be given back after
* usage using genl_family_put().
* Searches a previously allocated controller cache and looks for an entry
* that matches the specified family \c name. If a match is found successfully,
* the reference count of the matching object is increased by one before the
* objet is returned.
*
* @return Generic netlink family object or NULL if no match was found.
* @see genl_ctrl_alloc_cache()
* @see genl_ctrl_search()
* @see genl_family_put()
*
* @return Generic Netlink family object or NULL if no match was found.
*/
struct genl_family *genl_ctrl_search_by_name(struct nl_cache *cache,
const char *name)
const char *name)
{
struct genl_family *fam;
@ -250,14 +276,26 @@ struct genl_family *genl_ctrl_search_by_name(struct nl_cache *cache,
/** @} */
/**
* Resolve generic netlink family name to its identifier
* @arg sk Netlink socket.
* @arg name Name of generic netlink family
* @name Direct Resolvers
*
* Resolves the generic netlink family name to its identifer and returns
* it.
* These functions communicate directly with the kernel and do not require
* a cache to be kept up to date.
*
* @return A positive identifier or a negative error code.
* @{
*/
/**
* Resolve Generic Netlink family name to numeric identifier
* @arg sk Generic Netlink socket.
* @arg name Name of Generic Netlink family
*
* Resolves the Generic Netlink family name to the corresponding numeric
* family identifier. This function queries the kernel directly, use
* genl_ctrl_search_by_name() if you need to resolve multiple names.
*
* @see genl_ctrl_search_by_name()
*
* @return The numeric family identifier or a negative error code.
*/
int genl_ctrl_resolve(struct nl_sock *sk, const char *name)
{
@ -283,7 +321,7 @@ errout:
}
static int genl_ctrl_grp_by_name(const struct genl_family *family,
const char *grp_name)
const char *grp_name)
{
struct genl_family_grp *grp;
@ -296,8 +334,19 @@ static int genl_ctrl_grp_by_name(const struct genl_family *family,
return -NLE_OBJ_NOTFOUND;
}
/**
* Resolve Generic Netlink family group name
* @arg sk Generic Netlink socket
* @arg family_name Name of Generic Netlink family
* @arg grp_name Name of group to resolve
*
* Looks up the family object and resolves the group name to the numeric
* group identifier.
*
* @return Numeric group identifier or a negative error code.
*/
int genl_ctrl_resolve_grp(struct nl_sock *sk, const char *family_name,
const char *grp_name)
const char *grp_name)
{
struct nl_cache *cache;
struct genl_family *family;
@ -322,6 +371,7 @@ errout:
/** @} */
/** @cond SKIP */
static struct genl_cmd genl_cmds[] = {
{
.c_id = CTRL_CMD_NEWFAMILY,
@ -353,9 +403,7 @@ static struct genl_ops genl_ops = {
.o_ncmds = ARRAY_SIZE(genl_cmds),
};
/** @cond SKIP */
extern struct nl_object_ops genl_family_ops;
/** @endcond */
static struct nl_cache_ops genl_ctrl_ops = {
.co_name = "genl/family",
@ -376,5 +424,6 @@ static void __exit ctrl_exit(void)
{
genl_unregister(&genl_ctrl_ops);
}
/** @endcond */
/** @} */

View file

@ -6,13 +6,14 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
* Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
*/
/**
* @ingroup genl
* @defgroup genl_family Generic Netlink Family
* @brief
* @ingroup genl_ctrl
* @defgroup genl_family Generic Netlink Family Object
*
* Object representing a kernel side registered Generic Netlink family
*
* @{
*/
@ -32,7 +33,6 @@
#define FAMILY_ATTR_OPS 0x20
struct nl_object_ops genl_family_ops;
/** @endcond */
static void family_constructor(struct nl_object *c)
{
@ -166,18 +166,32 @@ static int family_compare(struct nl_object *_a, struct nl_object *_b,
return diff;
}
/** @endcond */
/**
* @name Family Object
* @name Object Allocation
* @{
*/
/**
* Allocate new Generic Netlink family object
*
* @return Newly allocated Generic Netlink family object or NULL.
*/
struct genl_family *genl_family_alloc(void)
{
return (struct genl_family *) nl_object_alloc(&genl_family_ops);
}
/**
* Release reference on Generic Netlink family object
* @arg family Generic Netlink family object
*
* Reduces the reference counter of a Generic Netlink family object by one.
* The object is freed after the last user has returned its reference.
*
* @see nl_object_put()
*/
void genl_family_put(struct genl_family *family)
{
nl_object_put((struct nl_object *) family);
@ -186,10 +200,16 @@ void genl_family_put(struct genl_family *family)
/** @} */
/**
* @name Attributes
* @name Numeric Identifier
* @{
*/
/**
* Return numeric identifier
* @arg family Generic Netlink family object
*
* @return Numeric identifier or 0 if not available.
*/
unsigned int genl_family_get_id(struct genl_family *family)
{
if (family->ce_mask & FAMILY_ATTR_ID)
@ -198,12 +218,30 @@ unsigned int genl_family_get_id(struct genl_family *family)
return GENL_ID_GENERATE;
}
/**
* Set the numeric identifier
* @arg family Generic Netlink family object
* @arg id New numeric identifier
*/
void genl_family_set_id(struct genl_family *family, unsigned int id)
{
family->gf_id = id;
family->ce_mask |= FAMILY_ATTR_ID;
}
/** @} */
/**
* @name Human Readable Name
* @{
*/
/**
* Return human readable name
* @arg family Generic Netlink family object
*
* @return Name of family or NULL if not available
*/
char *genl_family_get_name(struct genl_family *family)
{
if (family->ce_mask & FAMILY_ATTR_NAME)
@ -212,12 +250,28 @@ char *genl_family_get_name(struct genl_family *family)
return NULL;
}
/**
* Set human readable name
* @arg family Generic Netlink family object
* @arg name New human readable name
*/
void genl_family_set_name(struct genl_family *family, const char *name)
{
strncpy(family->gf_name, name, GENL_NAMSIZ-1);
family->ce_mask |= FAMILY_ATTR_NAME;
}
/**
* @name Interface Version
* @{
*/
/**
* Return interface version
* @arg family Generic Netlink family object
*
* @return Interface version or 0 if not available.
*/
uint8_t genl_family_get_version(struct genl_family *family)
{
if (family->ce_mask & FAMILY_ATTR_VERSION)
@ -226,12 +280,30 @@ uint8_t genl_family_get_version(struct genl_family *family)
return 0;
}
/**
* Set interface version
* @arg family Generic Netlink family object
* @arg version New interface version
*/
void genl_family_set_version(struct genl_family *family, uint8_t version)
{
family->gf_version = version;
family->ce_mask |= FAMILY_ATTR_VERSION;
}
/** @} */
/**
* @name Header Size
* @{
*/
/**
* Return user header size expected by kernel component
* @arg family Generic Netlink family object
*
* @return Expected header length or 0 if not available.
*/
uint32_t genl_family_get_hdrsize(struct genl_family *family)
{
if (family->ce_mask & FAMILY_ATTR_HDRSIZE)
@ -246,6 +318,13 @@ void genl_family_set_hdrsize(struct genl_family *family, uint32_t hdrsize)
family->ce_mask |= FAMILY_ATTR_HDRSIZE;
}
/** @} */
/**
* @name Maximum Expected Attribute
* @{
*/
uint32_t genl_family_get_maxattr(struct genl_family *family)
{
if (family->ce_mask & FAMILY_ATTR_MAXATTR)
@ -260,6 +339,13 @@ void genl_family_set_maxattr(struct genl_family *family, uint32_t maxattr)
family->ce_mask |= FAMILY_ATTR_MAXATTR;
}
/** @} */
/**
* @name Operations
* @{
*/
int genl_family_add_op(struct genl_family *family, int id, int flags)
{
struct genl_family_op *op;

View file

@ -12,80 +12,6 @@
/**
* @defgroup genl Generic Netlink Library (libnl-genl)
*
* @par Message Format
* @code
* <------- NLMSG_ALIGN(hlen) ------> <---- NLMSG_ALIGN(len) --->
* +----------------------------+- - -+- - - - - - - - - - -+- - -+
* | Header | Pad | Payload | Pad |
* | struct nlmsghdr | | | |
* +----------------------------+- - -+- - - - - - - - - - -+- - -+
* @endcode
* @code
* <-------- GENL_HDRLEN -------> <--- hdrlen -->
* <------- genlmsg_len(ghdr) ------>
* +------------------------+- - -+---------------+- - -+------------+
* | Generic Netlink Header | Pad | Family Header | Pad | Attributes |
* | struct genlmsghdr | | | | |
* +------------------------+- - -+---------------+- - -+------------+
* genlmsg_data(ghdr)--------------^ ^
* genlmsg_attrdata(ghdr, hdrlen)-------------------------
* @endcode
*
* @par Example
* @code
* #include <netlink/netlink.h>
* #include <netlink/genl/genl.h>
* #include <netlink/genl/ctrl.h>
*
* struct nl_sock *sock;
* struct nl_msg *msg;
* int family;
*
* // Allocate a new netlink socket
* sock = nl_socket_alloc();
*
* // Connect to generic netlink socket on kernel side
* genl_connect(sock);
*
* // Ask kernel to resolve family name to family id
* family = genl_ctrl_resolve(sock, "generic_netlink_family_name");
*
* // Construct a generic netlink by allocating a new message, fill in
* // the header and append a simple integer attribute.
* msg = nlmsg_alloc();
* genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_ECHO,
* CMD_FOO_GET, FOO_VERSION);
* nla_put_u32(msg, ATTR_FOO, 123);
*
* // Send message over netlink socket
* nl_send_auto_complete(sock, msg);
*
* // Free message
* nlmsg_free(msg);
*
* // Prepare socket to receive the answer by specifying the callback
* // function to be called for valid messages.
* nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, parse_cb, NULL);
*
* // Wait for the answer and receive it
* nl_recvmsgs_default(sock);
*
* static int parse_cb(struct nl_msg *msg, void *arg)
* {
* struct nlmsghdr *nlh = nlmsg_hdr(msg);
* struct nlattr *attrs[ATTR_MAX+1];
*
* // Validate message and parse attributes
* genlmsg_parse(nlh, 0, attrs, ATTR_MAX, policy);
*
* if (attrs[ATTR_FOO]) {
* uint32_t value = nla_get_u32(attrs[ATTR_FOO]);
* ...
* }
*
* return 0;
* }
* @endcode
* @{
*/
@ -95,10 +21,27 @@
#include <netlink/utils.h>
/**
* @name Socket Creating
* @name Generic Netlink Socket
* @{
*/
/**
* Connect a Generic Netlink socket
* @arg sk Unconnected Netlink socket
*
* This function expects a struct nl_socket object previously allocated via
* nl_socket_alloc(). It calls nl_connect() to create the local socket file
* descriptor and binds the socket to the \c NETLINK_GENERIC Netlink protocol.
*
* Using this function is equivalent to:
* @code
* nl_connect(sk, NETLINK_GENERIC);
* @endcode
*
* @see nl_connect()
*
* @return 0 on success or a negative error code.
*/
int genl_connect(struct nl_sock *sk)
{
return nl_connect(sk, NETLINK_GENERIC);
@ -107,20 +50,34 @@ int genl_connect(struct nl_sock *sk)
/** @} */
/**
* @name Sending
* @name Sending Data
* @{
*/
/**
* Send trivial generic netlink message
* @arg sk Netlink socket.
* @arg family Generic netlink family
* @arg cmd Command
* @arg version Version
* @arg flags Additional netlink message flags.
* Send a Generic Netlink message consisting only of a header
* @arg sk Generic Netlink socket
* @arg family Numeric family identifier
* @arg cmd Numeric command identifier
* @arg version Interface version
* @arg flags Additional Netlink message flags (optional)
*
* Fills out a routing netlink request message and sends it out
* using nl_send_simple().
* This function is a shortcut for sending a Generic Netlink message without
* any message payload. The message will only consist of the Netlink and
* Generic Netlink headers. The header is constructed based on the specified
* parameters and passed on to nl_send_simple() to send it on the specified
* socket.
*
* @par Example:
* @code
* #include <netlink/genl/genl.h>
* #include <linux/genetlink.h>
*
* err = genl_send_simple(sk, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, CTRL_VERSION,
* NLM_F_DUMP);
* @endcode
*
* @see nl_send_simple()
*
* @return 0 on success or a negative error code.
*/
@ -137,12 +94,26 @@ int genl_send_simple(struct nl_sock *sk, int family, int cmd,
/** @} */
/**
* @name Message Parsing
* @{
*/
/**
* Validate Generic Netlink message headers
* @arg nlh Pointer to Netlink message header
* @arg hdrlen Length of user header
*
* Verifies the integrity of the Netlink and Generic Netlink headers by
* enforcing the following requirements:
* - Valid Netlink message header (nlmsg_valid_hdr())
* - Presence of a complete Generic Netlink header
* - At least \c hdrlen bytes of payload included after the generic
* netlink header.
*
* @return A positive integer (true) if the headers are valid or
* 0 (false) if not.
*/
int genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen)
{
struct genlmsghdr *ghdr;
@ -157,8 +128,28 @@ int genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen)
return 1;
}
/**
* Validate Generic Netlink message including attributes
* @arg nlh Pointer to Netlink message header
* @arg hdrlen Length of user header
* @arg maxtype Maximum attribtue id expected
* @arg policy Attribute validation policy
*
* Verifies the validity of the Netlink and Generic Netlink headers using
* genlmsg_valid_hdr() and calls nla_validate() on the message payload to
* verify the integrity of eventual attributes.
*
* @note You may call genlmsg_parse() directly to perform validation and
* parsing in a single step.
*
* @see genlmsg_valid_hdr()
* @see nla_validate()
* @see genlmsg_parse()
*
* @return 0 on success or a negative error code.
*/
int genlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype,
struct nla_policy *policy)
struct nla_policy *policy)
{
struct genlmsghdr *ghdr;
@ -170,6 +161,33 @@ int genlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype,
genlmsg_attrlen(ghdr, hdrlen), maxtype, policy);
}
/**
* Parse Generic Netlink message including attributes
* @arg nlh Pointer to Netlink message header
* @arg hdrlen Length of user header
* @arg tb Array to store parsed attributes
* @arg maxtype Maximum attribute id expected
* @arg policy Attribute validation policy
*
* Verifies the validity of the Netlink and Generic Netlink headers using
* genlmsg_valid_hdr() and calls nla_parse() on the message payload to
* parse eventual attributes.
*
* @par Example:
* @code
* struct nlattr *attrs[MY_TYPE_MAX+1];
*
* if ((err = genlsmg_parse(nlmsg_nlh(msg), sizeof(struct my_hdr), attrs,
* MY_TYPE_MAX, attr_policy)) < 0)
* // ERROR
* @endcode
*
* @see genlmsg_valid_hdr()
* @see genlmsg_validate()
* @see nla_parse()
*
* @return 0 on success or a negative error code.
*/
int genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
int maxtype, struct nla_policy *policy)
{
@ -184,29 +202,44 @@ int genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
}
/**
* Get head of message payload
* @arg gnlh genetlink messsage header
* Return pointer to message payload
* @arg gnlh Generic Netlink message header
*
* Calculates the pointer to the message payload based on the pointer
* to the generic netlink message header.
*
* @note Depending on whether your own message format uses a header, the
* returned pointer may in fact point to the user header.
*
* @return Pointer to generic netlink message
*/
void *genlmsg_data(const struct genlmsghdr *gnlh)
{
return ((unsigned char *) gnlh + GENL_HDRLEN);
}
/**
* Get lenght of message payload
* @arg gnlh genetlink message header
* Return length of message payload
* @arg gnlh Generic Netlink message header
*
* @return Length of user payload including an eventual user header in
* number of bytes.
*/
int genlmsg_len(const struct genlmsghdr *gnlh)
{
struct nlmsghdr *nlh = (struct nlmsghdr *)((unsigned char *)gnlh -
NLMSG_HDRLEN);
struct nlmsghdr *nlh;
nlh = (struct nlmsghdr *)((unsigned char *) gnlh - NLMSG_HDRLEN);
return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN);
}
/**
* Get head of attribute data
* @arg gnlh generic netlink message header
* @arg hdrlen length of family specific header
* Return pointer to message attributes
* @arg gnlh Generic Netlink message header
* @arg hdrlen Length of user header
*
* @return Pointer to the start of the message's attributes section.
*/
struct nlattr *genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen)
{
@ -214,9 +247,12 @@ struct nlattr *genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen)
}
/**
* Get length of attribute data
* @arg gnlh generic netlink message header
* @arg hdrlen length of family specific header
* Return length of message attributes
* @arg gnlh Generic Netlink message header
* @arg hdrlen Length of user header
*
* @return Length of the message section containing attributes in number
* of bytes.
*/
int genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen)
{
@ -226,24 +262,45 @@ int genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen)
/** @} */
/**
* @name Message Building
* @name Message Construction
* @{
*/
/**
* Add generic netlink header to netlink message
* @arg msg netlink message
* @arg pid netlink process id or NL_AUTO_PID
* @arg seq sequence number of message or NL_AUTO_SEQ
* @arg family generic netlink family
* @arg hdrlen length of user specific header
* @arg flags message flags
* @arg cmd generic netlink command
* @arg version protocol version
* Add Generic Netlink headers to Netlink message
* @arg msg Netlink message object
* @arg port Netlink port or NL_AUTO_PORT
* @arg seq Sequence number of message or NL_AUTO_SEQ
* @arg family Numeric family identifier
* @arg hdrlen Length of user header
* @arg flags Additional Netlink message flags (optional)
* @arg cmd Numeric command identifier
* @arg version Interface version
*
* Returns pointer to user specific header.
* Calls nlmsg_put() on the specified message object to reserve space for
* the Netlink header, the Generic Netlink header, and a user header of
* specified length. Fills out the header fields with the specified
* parameters.
*
* @par Example:
* @code
* struct nl_msg *msg;
* struct my_hdr *user_hdr;
*
* if (!(msg = nlmsg_alloc()))
* // ERROR
*
* user_hdr = genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, family_id,
* sizeof(struct my_hdr), 0, MY_CMD_FOO, 0);
* if (!user_hdr)
* // ERROR
* @endcode
*
* @see nlmsg_put()
*
* Returns Pointer to user header or NULL if an error occurred.
*/
void *genlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq, int family,
void *genlmsg_put(struct nl_msg *msg, uint32_t port, uint32_t seq, int family,
int hdrlen, int flags, uint8_t cmd, uint8_t version)
{
struct nlmsghdr *nlh;
@ -252,7 +309,7 @@ void *genlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq, int family,
.version = version,
};
nlh = nlmsg_put(msg, pid, seq, family, GENL_HDRLEN + hdrlen, flags);
nlh = nlmsg_put(msg, port, seq, family, GENL_HDRLEN + hdrlen, flags);
if (nlh == NULL)
return NULL;

View file

@ -6,77 +6,15 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
* Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
*/
/**
* @ingroup genl
* @defgroup genl_mngt Management
* @defgroup genl_mngt Family and Operations Management
*
* @par 1) Registering a generic netlink module
* @code
* #include <netlink/genl/mngt.h>
* Registering Generic Netlink Families and Commands
*
* // First step is to define all the commands being used in
* // particular generic netlink family. The ID and name are
* // mandatory to be filled out. A callback function and
* // most the attribute policy that comes with it must be
* // defined for commands expected to be issued towards
* // userspace.
* static struct genl_cmd foo_cmds[] = {
* {
* .c_id = FOO_CMD_NEW,
* .c_name = "NEWFOO" ,
* .c_maxattr = FOO_ATTR_MAX,
* .c_attr_policy = foo_policy,
* .c_msg_parser = foo_msg_parser,
* },
* {
* .c_id = FOO_CMD_DEL,
* .c_name = "DELFOO" ,
* },
* };
*
* // The list of commands must then be integrated into a
* // struct genl_ops serving as handle for this particular
* // family.
* static struct genl_ops my_genl_ops = {
* .o_cmds = foo_cmds,
* .o_ncmds = ARRAY_SIZE(foo_cmds),
* };
*
* // Using the above struct genl_ops an arbitary number of
* // cache handles can be associated to it.
* //
* // The macro GENL_HDRSIZE() must be used to specify the
* // length of the header to automatically take headers on
* // generic layers into account.
* //
* // The macro GENL_FAMILY() is used to represent the generic
* // netlink family id.
* static struct nl_cache_ops genl_foo_ops = {
* .co_name = "genl/foo",
* .co_hdrsize = GENL_HDRSIZE(sizeof(struct my_hdr)),
* .co_msgtypes = GENL_FAMILY(GENL_ID_GENERATE, "foo"),
* .co_genl = &my_genl_ops,
* .co_protocol = NETLINK_GENERIC,
* .co_request_update = foo_request_update,
* .co_obj_ops = &genl_foo_ops,
* };
*
* // Finally each cache handle for a generic netlink family
* // must be registered using genl_register().
* static void __init foo_init(void)
* {
* genl_register(&genl_foo_ops);
* }
*
* // ... respectively unregsted again.
* static void __exit foo_exit(void)
* {
* genl_unregister(&genl_foo_ops);
* }
* @endcode
* @{
*/
@ -88,6 +26,8 @@
#include <netlink/genl/ctrl.h>
#include <netlink/utils.h>
/** @cond SKIP */
static NL_LIST_HEAD(genl_ops_list);
static int genl_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
@ -159,15 +99,18 @@ char *genl_op2name(int family, int op, char *buf, size_t len)
return NULL;
}
/** @endcond */
/**
* @name Register/Unregister
* @name Registration (Cache Based)
* @{
*/
/**
* Register generic netlink operations
* @arg ops cache operations
* Register Generic Netlink family backed cache
* @arg ops Cache operations definition
*
* @return 0 on success or a negative error code.
*/
int genl_register(struct nl_cache_ops *ops)
{
@ -203,8 +146,8 @@ errout:
}
/**
* Unregister generic netlink operations
* @arg ops cache operations
* Unregister cache based Generic Netlink family
* @arg ops Cache operations definition
*/
void genl_unregister(struct nl_cache_ops *ops)
{
@ -217,11 +160,7 @@ void genl_unregister(struct nl_cache_ops *ops)
/** @} */
/**
* @name Resolving ID/Name
* @{
*/
/** @cond SKIP */
static int __genl_ops_resolve(struct nl_cache *ctrl, struct genl_ops *ops)
{
struct genl_family *family;
@ -236,7 +175,22 @@ static int __genl_ops_resolve(struct nl_cache *ctrl, struct genl_ops *ops)
return -NLE_OBJ_NOTFOUND;
}
/** @endcond */
/**
* @name Resolving the name of registered families
* @{
*/
/**
* Resolve a single Generic Netlink family
* @arg sk Generic Netlink socket
* @arg ops Generic Netlink family definition
*
* Resolves the family name to its numeric identifier.
*
* @return 0 on success or a negative error code.
*/
int genl_ops_resolve(struct nl_sock *sk, struct genl_ops *ops)
{
struct nl_cache *ctrl;
@ -252,6 +206,19 @@ errout:
return err;
}
/**
* Resolve all registered Generic Netlink families
* @arg sk Generic Netlink socket
*
* Walks through all local Generic Netlink families that have been registered
* using genl_register() and resolves the name of each family to the
* corresponding numeric identifier.
*
* @see genl_register()
* @see genl_ops_resolve()
*
* @return 0 on success or a negative error code.
*/
int genl_mngt_resolve(struct nl_sock *sk)
{
struct nl_cache *ctrl;
@ -272,5 +239,4 @@ errout:
/** @} */
/** @} */