diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2010-04-03 08:29:16 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2010-04-03 13:26:44 +0200 |
commit | 8ce5d4ca70884654988eb86734cb3022e0b71995 (patch) | |
tree | a42c6a5b87d5b6c2ff01446f127824e355de3ee8 /examples/rtnl-route-dump.c | |
parent | ba57ffc48d3a97421c8358947bc8cf9f2e7ff7c6 (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 <pablo@netfilter.org>
Diffstat (limited to 'examples/rtnl-route-dump.c')
-rw-r--r-- | examples/rtnl-route-dump.c | 55 |
1 files changed, 52 insertions, 3 deletions
diff --git a/examples/rtnl-route-dump.c b/examples/rtnl-route-dump.c index e8f3a0c..eb36bbc 100644 --- a/examples/rtnl-route-dump.c +++ b/examples/rtnl-route-dump.c @@ -7,6 +7,22 @@ #include <linux/if_link.h> #include <linux/rtnetlink.h> +static int data_attr_cb2(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = (const struct nlattr **)data; + int type = mnl_attr_get_type(attr); + + if (mnl_attr_type_invalid(attr, RTAX_MAX) < 0) { + perror("mnl_attr_type_invalid"); + return MNL_CB_ERROR; + } + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + return MNL_CB_OK; +} + static void attributes_show_ipv4(struct nlattr *tb[]) { if (tb[RTA_TABLE]) { @@ -35,7 +51,7 @@ static void attributes_show_ipv4(struct nlattr *tb[]) int i; struct nlattr *tbx[RTAX_MAX+1] = {}; - mnl_attr_parse_nested(tb[RTA_METRICS], tbx, RTAX_MAX); + mnl_attr_parse_nested(tb[RTA_METRICS], data_attr_cb2, tbx); for (i=0; i<RTAX_MAX; i++) { if (tbx[i]) { @@ -47,9 +63,42 @@ static void attributes_show_ipv4(struct nlattr *tb[]) printf("\n"); } +static int data_attr_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = (const struct nlattr **)data; + int type = mnl_attr_get_type(attr); + + if (mnl_attr_type_invalid(attr, RTA_MAX) < 0) { + perror("mnl_attr_type_invalid"); + return MNL_CB_ERROR; + } + + switch(type) { + case RTA_TABLE: + case RTA_DST: + case RTA_SRC: + case RTA_OIF: + case RTA_FLOW: + case RTA_PREFSRC: + case RTA_GATEWAY: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + case RTA_METRICS: + if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + } + tb[type] = attr; + return MNL_CB_OK; +} + static int data_cb(const struct nlmsghdr *nlh, void *data) { - /* parse() ya está inicializando este array, qué hacer ? */ struct nlattr *tb[RTA_MAX+1] = {}; struct rtmsg *rm = mnl_nlmsg_get_data(nlh); int len = mnl_nlmsg_get_len(nlh); @@ -131,7 +180,7 @@ static int data_cb(const struct nlmsghdr *nlh, void *data) */ printf("flags=%x\n", rm->rtm_flags); - mnl_attr_parse_at_offset(nlh, sizeof(*rm), tb, RTA_MAX); + mnl_attr_parse(nlh, sizeof(*rm), data_attr_cb, tb); switch(rm->rtm_family) { case AF_INET: |