Added additional parsing and validation functions for generic netlink
Also adds better example documentation for generic netlink
This commit is contained in:
parent
373bc78545
commit
c8a0a5cdfb
6 changed files with 108 additions and 33 deletions
|
@ -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);
|
||||
|
|
|
@ -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 **,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
114
lib/genl/genl.c
114
lib/genl/genl.c
|
@ -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
|
||||
|
|
12
lib/msg.c
12
lib/msg.c
|
@ -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),
|
||||
|
|
Loading…
Add table
Reference in a new issue