]> granicus.if.org Git - libnl/commitdiff
Added additional parsing and validation functions for generic netlink
authorThomas Graf <tgr@deb.localdomain>
Thu, 10 Jan 2008 11:35:38 +0000 (12:35 +0100)
committerThomas Graf <tgr@deb.localdomain>
Thu, 10 Jan 2008 11:35:38 +0000 (12:35 +0100)
Also adds better example documentation for generic netlink

include/netlink/genl/genl.h
include/netlink/msg.h
lib/cache.c
lib/defs.h
lib/genl/genl.c
lib/msg.c

index 623ec3f3198bf6855353f21bdac917a3692d5664..de142d07bc7a1a65edb7fcd128f3a562287e4f6d 100644 (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);
index d7da2cfbd133425511fc3e9a0835fb44d4780b2a..263503af3d60b2ace0ce6677cf0fd93be125c6fd 100644 (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 **,
index c770765c15b83c4a6e84a61ad20266f81f504f21..c1fbea61a26fbd4a0e1e625b004d6960baac3180 100644 (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;
index aa85c1623cab6aacaf8a55dd27f93d89593ef7de..ac3916c6fa285cd17b3c9068efa4aeb119ecda4e 100644 (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 */
index c600579460169b55ffc2182e6e03f2ec60a3fdd0..cb067a59bc52068bdd406f56659a2771c314f74c 100644 (file)
  * 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
- * msg = nlmsg_alloc();
+ * // Allocate a new netlink socket
+ * sock = nl_handle_alloc();
  *
- * // 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);
+ * // Connect to generic netlink socket on kernel side
+ * genl_connect(sock);
  *
- * // Fill out your own family specific header.
- * hdr->a = 1;
- * hdr->b = 2;
+ * // Ask kernel to resolve family name to family id
+ * family = genl_ctrl_resolve(sock, "generic_netlink_family_name");
  *
- * // Append the optional attributes.
- * nla_put_u32(msg, 1, 0x10);
+ * // 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);
  *
- * // Message is ready to be sent.
- * nl_send_auto_complete(nl_handle, msg);
+ * // Send message over netlink socket
+ * nl_send_auto_complete(sock, 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
index 589fcb9cfbd0d5352ea46206c69a44dd2594d47c..3ae890911ab42678ea6ecf35c2ee8665e016e92b 100644 (file)
--- a/lib/msg.c
+++ b/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),