Added additional parsing and validation functions for generic netlink

Also adds better example documentation for generic netlink
This commit is contained in:
Thomas Graf 2008-01-10 12:35:38 +01:00
parent 373bc78545
commit c8a0a5cdfb
6 changed files with 108 additions and 33 deletions

View file

@ -13,6 +13,8 @@
#define NETLINK_GENL_H_
#include <netlink/netlink.h>
#include <netlink/msg.h>
#include <netlink/attr.h>
#ifdef __cplusplus
extern "C" {
@ -25,6 +27,12 @@ extern int genl_send_simple(struct nl_handle *, int, int,
extern void * genlmsg_put(struct nl_msg *, uint32_t, uint32_t,
int, int, int, uint8_t, uint8_t);
extern int genlmsg_valid_hdr(struct nlmsghdr *, int);
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 void * genlmsg_data(const struct genlmsghdr *);
extern int genlmsg_len(const struct genlmsghdr *);
extern struct nlattr * genlmsg_attrdata(const struct genlmsghdr *, int);

View file

@ -59,6 +59,7 @@ extern struct nlattr * nlmsg_attrdata(const struct nlmsghdr *, int);
extern int nlmsg_attrlen(const struct nlmsghdr *, int);
/* message parsing */
extern int nlmsg_valid_hdr(const struct nlmsghdr *, int);
extern int nlmsg_ok(const struct nlmsghdr *, int);
extern struct nlmsghdr * nlmsg_next(struct nlmsghdr *, int *);
extern int nlmsg_parse(struct nlmsghdr *, int, struct nlattr **,

View file

@ -604,7 +604,7 @@ int nl_cache_parse(struct nl_cache_ops *ops, struct sockaddr_nl *who,
{
int i, err;
if (nlh->nlmsg_len < nlmsg_msg_size(ops->co_hdrsize)) {
if (!nlmsg_valid_hdr(nlh, ops->co_hdrsize)) {
err = nl_error(EINVAL, "netlink message too short to be "
"of kind %s", ops->co_name);
goto errout;

View file

@ -8,13 +8,13 @@
#define PACKAGE_NAME "libnl"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "libnl 1.0-pre8"
#define PACKAGE_STRING "libnl 1.0-pre9"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "libnl"
/* Define to the version of this package. */
#define PACKAGE_VERSION "1.0-pre8"
#define PACKAGE_VERSION "1.0-pre9"
/* verbose errors */
/* #undef VERBOSE_ERRORS */

View file

@ -32,43 +32,61 @@
* genlmsg_attrdata(ghdr, hdrlen)-------------------------
* @endcode
*
* @par 1) Creating a new generic netlink message
* @par Example
* @code
* #include <netlink/netlink.h>
* #include <netlink/genl/genl.h>
* #include <netlink/genl/ctrl.h>
*
* struct nl_handle *sock;
* struct nl_msg *msg;
* struct myhdr {
* int a;
* int b;
* } *hdr;
* int family;
*
* // Create a new empty netlink message
* // Allocate a new netlink socket
* sock = nl_handle_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);
*
* // Append the netlink and generic netlink message header, this
* // operation also reserves room for the family specific header.
* hdr = genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, sizeof(hdr),
* NLM_F_ECHO, MYOP, VERSION);
* // Send message over netlink socket
* nl_send_auto_complete(sock, msg);
*
* // Fill out your own family specific header.
* hdr->a = 1;
* hdr->b = 2;
*
* // Append the optional attributes.
* nla_put_u32(msg, 1, 0x10);
*
* // Message is ready to be sent.
* nl_send_auto_complete(nl_handle, msg);
*
* // All done? Free the message.
* // Free message
* nlmsg_free(msg);
* @endcode
*
* @par 2) Sending of trivial messages
* @code
* // For trivial messages not requiring any family specific header or
* // attributes, genl_send_simple() may be used to send messages directly.
* genl_send_simple(nl_handle, family, MY_SIMPLE_CMD, VERSION, 0);
* // 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
* @{
*/
#include <netlink-generic.h>
@ -125,6 +143,46 @@ int genl_send_simple(struct nl_handle *handle, int family, int cmd,
* @{
*/
int genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen)
{
struct genlmsghdr *ghdr;
if (!nlmsg_valid_hdr(nlh, GENL_HDRLEN))
return 0;
ghdr = nlmsg_data(nlh);
if (genlmsg_len(ghdr) < NLMSG_ALIGN(hdrlen))
return 0;
return 1;
}
int genlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype,
struct nla_policy *policy)
{
struct genlmsghdr *ghdr;
if (!genlmsg_valid_hdr(nlh, hdrlen))
return nl_errno(EINVAL);
ghdr = nlmsg_data(nlh);
return nla_validate(genlmsg_attrdata(ghdr, hdrlen),
genlmsg_attrlen(ghdr, hdrlen), maxtype, policy);
}
int genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
int maxtype, struct nla_policy *policy)
{
struct genlmsghdr *ghdr;
if (!genlmsg_valid_hdr(nlh, hdrlen))
return nl_errno(EINVAL);
ghdr = nlmsg_data(nlh);
return nla_parse(tb, maxtype, genlmsg_attrdata(ghdr, hdrlen),
genlmsg_attrlen(ghdr, hdrlen), policy);
}
/**
* Get head of message payload
* @arg gnlh genetlink messsage header

View file

@ -261,6 +261,14 @@ int nlmsg_attrlen(const struct nlmsghdr *nlh, int hdrlen)
* @{
*/
int nlmsg_valid_hdr(const struct nlmsghdr *nlh, int hdrlen)
{
if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
return 0;
return 1;
}
/**
* check if the netlink message fits into the remaining bytes
* @arg nlh netlink message header
@ -303,7 +311,7 @@ struct nlmsghdr *nlmsg_next(struct nlmsghdr *nlh, int *remaining)
int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
int maxtype, struct nla_policy *policy)
{
if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
if (!nlmsg_valid_hdr(nlh, hdrlen))
return nl_errno(EINVAL);
return nla_parse(tb, maxtype, nlmsg_attrdata(nlh, hdrlen),
@ -334,7 +342,7 @@ struct nlattr *nlmsg_find_attr(struct nlmsghdr *nlh, int hdrlen, int attrtype)
int nlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype,
struct nla_policy *policy)
{
if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
if (!nlmsg_valid_hdr(nlh, hdrlen))
return nl_errno(EINVAL);
return nla_validate(nlmsg_attrdata(nlh, hdrlen),