path: root/include/libmnl/libmnl.h
diff options
authorPablo Neira Ayuso <>2010-04-03 08:29:16 +0200
committerPablo Neira Ayuso <>2010-04-03 13:26:44 +0200
commit8ce5d4ca70884654988eb86734cb3022e0b71995 (patch)
treea42c6a5b87d5b6c2ff01446f127824e355de3ee8 /include/libmnl/libmnl.h
parentba57ffc48d3a97421c8358947bc8cf9f2e7ff7c6 (diff)
add validation infrastructure and rework attribute parsing
This patch includes the new validation infrastructure which is decoupled from the attribute parsing. It is composed of: - mnl_attr_type_invalid: that allows to check if the attribute type is valid (ie. the type is not higher than WXYZ_MAX). - mnl_attr_validate: that allows to validate that there's enough room for the attribute data. The patch includes the rework of the attribute parsers. Now, you don't have to use an array of pointer to store the result of the parsing, you can use whatever data structure instead. The prototype as it follows: typedef int (*mnl_attr_cb_t)(const struct nlattr *attr, void *data); extern int mnl_attr_parse(const struct nlmsghdr *nlh, int offset, mnl_attr_cb_t cb, void *data) There are three versions of rtnl-link-dump.c that show how attribute parsing can be done now. Probably that many examples are not good idea, I may remove some of them from the tree in the future. This patch also merges mnl_attr_parse_at_offset into mnl_attr_parse. This patch modifies MNL_ALIGN so that we can use it in static arrays (the use of mnl_align() is not allowed in compilation time to initialize an array field). I have added the mnl_attr_for_each() macro and I have changed mnl_attr_for_each_nested() to declare the length variable internally. Signed-off-by: Pablo Neira Ayuso <>
Diffstat (limited to 'include/libmnl/libmnl.h')
1 files changed, 42 insertions, 11 deletions
diff --git a/include/libmnl/libmnl.h b/include/libmnl/libmnl.h
index e114cef..6a2b8a6 100644
--- a/include/libmnl/libmnl.h
+++ b/include/libmnl/libmnl.h
@@ -29,8 +29,9 @@ extern int mnl_socket_getsockopt(const struct mnl_socket *nl, int type, void *bu
* generic netlink message API
-#define MNL_ALIGNTO 4
-#define MNL_NLMSG_HDRLEN mnl_align(sizeof(struct nlmsghdr))
+#define MNL_ALIGNTO 4
+#define MNL_ALIGN(len) (((len)+MNL_ALIGNTO-1) & ~(MNL_ALIGNTO-1))
+#define MNL_NLMSG_HDRLEN MNL_ALIGN(sizeof(struct nlmsghdr))
extern int mnl_align(int len);
extern size_t mnl_nlmsg_size(int len);
@@ -60,7 +61,7 @@ extern void mnl_nlmsg_print(const struct nlmsghdr *nlh);
* generic netlink attributes API
-#define MNL_ATTR_HDRLEN mnl_align(sizeof(struct nlattr))
+#define MNL_ATTR_HDRLEN MNL_ALIGN(sizeof(struct nlattr))
/* TLV attribute getters */
extern uint16_t mnl_attr_get_type(const struct nlattr *attr);
@@ -82,17 +83,47 @@ extern void mnl_attr_put_u64(struct nlmsghdr *nlh, int type, uint64_t data);
extern void mnl_attr_put_str(struct nlmsghdr *nlh, int type, const void *data);
extern void mnl_attr_put_str_null(struct nlmsghdr *nlh, int type, const void *data);
-/* TLV attribute parsers */
-extern int mnl_attr_parse(const struct nlmsghdr *nlh, struct nlattr *tb[], int max);
-extern int mnl_attr_parse_at_offset(const struct nlmsghdr *nlh, int offset, struct nlattr *tb[], int max);
-extern int mnl_attr_parse_nested(const struct nlattr *attr, struct nlattr *tb[], int max);
+/* TLV validation */
+enum mnl_attr_data_type {
+extern int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type);
+extern int mnl_attr_validate2(const struct nlattr *attr, enum mnl_attr_data_type type, int minlen);
+/* TLV iterators */
extern int mnl_attr_ok(const struct nlattr *attr, int len);
extern struct nlattr *mnl_attr_next(const struct nlattr *attr, int *len);
-#define mnl_attr_for_each_nested(pos, head, len) \
- for (pos = mnl_attr_get_data(head), len = mnl_attr_get_len(head); \
- mnl_attr_ok(pos, len); \
- pos = mnl_attr_next(pos, &(len)))
+#define mnl_attr_for_each(attr, nlh, offset) \
+ int __len__ = mnl_nlmsg_payload_size(nlh); \
+ for (attr = mnl_nlmsg_get_data_offset(nlh, offset); \
+ mnl_attr_ok(attr, __len__); \
+ attr = mnl_attr_next(attr, &(__len__)))
+#define mnl_attr_for_each_nested(attr, nest) \
+ int __len__ = mnl_attr_get_len(nest); \
+ for (pos = mnl_attr_get_data(nest); \
+ mnl_attr_ok(attr, __len__); \
+ pos = mnl_attr_next(attr, &(__len__)))
+/* TLV callback-based attribute parsers */
+typedef int (*mnl_attr_cb_t)(const struct nlattr *attr, void *data);
+extern int mnl_attr_parse(const struct nlmsghdr *nlh, int offset, mnl_attr_cb_t cb, void *data);
+extern int mnl_attr_parse_nested(const struct nlattr *attr, mnl_attr_cb_t cb, void *data);
* callback API