From 3ed3c75a9a7a25ba9e8773e8830ab5b3914ef51b Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 25 Jan 2013 15:56:17 +0100 Subject: rule: add protocol and flags support for xtables over nftables Signed-off-by: Pablo Neira Ayuso --- include/libnftables/rule.h | 2 + include/linux/netfilter/nf_tables.h | 14 +++++++ src/rule.c | 83 +++++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+) diff --git a/include/libnftables/rule.h b/include/libnftables/rule.h index 129dd29..e17799a 100644 --- a/include/libnftables/rule.h +++ b/include/libnftables/rule.h @@ -19,6 +19,8 @@ enum { NFT_RULE_ATTR_CHAIN, NFT_RULE_ATTR_HANDLE, NFT_RULE_ATTR_FLAGS, + NFT_RULE_ATTR_COMPAT_PROTO, + NFT_RULE_ATTR_COMPAT_FLAGS, }; void nft_rule_attr_set(struct nft_rule *r, uint16_t attr, void *data); diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h index c07d1d3..c2dae4e 100644 --- a/include/linux/netfilter/nf_tables.h +++ b/include/linux/netfilter/nf_tables.h @@ -98,10 +98,24 @@ enum nft_rule_attributes { NFTA_RULE_HANDLE, NFTA_RULE_EXPRESSIONS, NFTA_RULE_FLAGS, + NFTA_RULE_COMPAT, __NFTA_RULE_MAX }; #define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1) +enum nft_rule_compat_flags { + NFT_RULE_COMPAT_F_INV = (1 << 1), + NFT_RULE_COMPAT_F_MASK = NFT_RULE_COMPAT_F_INV, +}; + +enum nft_rule_compat_attributes { + NFTA_RULE_COMPAT_UNSPEC, + NFTA_RULE_COMPAT_PROTO, + NFTA_RULE_COMPAT_FLAGS, + __NFTA_RULE_COMPAT_MAX +}; +#define NFTA_RULE_COMPAT_MAX (__NFTA_RULE_COMPAT_MAX - 1) + /** * enum nft_set_flags - nf_tables set flags * diff --git a/src/rule.c b/src/rule.c index 4d61fbd..6c4aa4c 100644 --- a/src/rule.c +++ b/src/rule.c @@ -36,6 +36,10 @@ struct nft_rule { uint8_t family; uint32_t rule_flags; uint64_t handle; + struct { + uint32_t flags; + uint32_t proto; + } compat; struct list_head expr_list; }; @@ -86,6 +90,12 @@ void nft_rule_attr_set(struct nft_rule *r, uint16_t attr, void *data) case NFT_RULE_ATTR_FLAGS: r->rule_flags = *((uint32_t *)data); break; + case NFT_RULE_ATTR_COMPAT_PROTO: + r->compat.proto = *((uint32_t *)data); + break; + case NFT_RULE_ATTR_COMPAT_FLAGS: + r->compat.flags = *((uint32_t *)data); + break; default: return; } @@ -143,6 +153,18 @@ void *nft_rule_attr_get(struct nft_rule *r, uint16_t attr) else return NULL; break; + case NFT_RULE_ATTR_COMPAT_PROTO: + if (r->flags & (1 << NFT_RULE_ATTR_COMPAT_PROTO)) + return &r->compat.proto; + else + return NULL; + break; + case NFT_RULE_ATTR_COMPAT_FLAGS: + if (r->flags & (1 << NFT_RULE_ATTR_COMPAT_FLAGS)) + return &r->compat.flags; + else + return NULL; + break; default: return NULL; } @@ -216,6 +238,17 @@ void nft_rule_nlmsg_build_payload(struct nlmsghdr *nlh, struct nft_rule *r) nft_rule_expr_build_payload(nlh, expr); } mnl_attr_nest_end(nlh, nest); + + if (r->flags & (1 << NFT_RULE_ATTR_COMPAT_PROTO) && + r->flags & (1 << NFT_RULE_ATTR_COMPAT_FLAGS)) { + + nest = mnl_attr_nest_start(nlh, NFTA_RULE_COMPAT); + mnl_attr_put_u32(nlh, NFTA_RULE_COMPAT_PROTO, + htonl(r->compat.proto)); + mnl_attr_put_u32(nlh, NFTA_RULE_COMPAT_FLAGS, + htonl(r->compat.flags)); + mnl_attr_nest_end(nlh, nest); + } } EXPORT_SYMBOL(nft_rule_nlmsg_build_payload); @@ -253,6 +286,12 @@ static int nft_rule_parse_attr_cb(const struct nlattr *attr, void *data) return MNL_CB_ERROR; } break; + case NFTA_RULE_COMPAT: + if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; } tb[type] = attr; @@ -322,6 +361,48 @@ static int nft_rule_parse_expr(struct nlattr *nest, struct nft_rule *r) return 0; } +static int nft_rule_parse_compat_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = data; + int type = mnl_attr_get_type(attr); + + if (mnl_attr_type_valid(attr, NFTA_RULE_COMPAT_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case NFTA_RULE_COMPAT_PROTO: + case NFTA_RULE_COMPAT_FLAGS: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + } + + tb[type] = attr; + return MNL_CB_OK; +} + +static int nft_rule_parse_compat(struct nlattr *nest, struct nft_rule *r) +{ + struct nlattr *tb[NFTA_RULE_COMPAT_MAX+1] = {}; + + if (mnl_attr_parse_nested(nest, nft_rule_parse_compat_cb, tb) < 0) + return -1; + + if (tb[NFTA_RULE_COMPAT_PROTO]) { + r->compat.proto = + ntohl(mnl_attr_get_u32(tb[NFTA_RULE_COMPAT_PROTO])); + r->flags |= (1 << NFT_RULE_ATTR_COMPAT_PROTO); + } + if (tb[NFTA_RULE_COMPAT_FLAGS]) { + r->compat.flags = + ntohl(mnl_attr_get_u32(tb[NFTA_RULE_COMPAT_FLAGS])); + r->flags |= (1 << NFT_RULE_ATTR_COMPAT_FLAGS); + } + return 0; +} + int nft_rule_nlmsg_parse(const struct nlmsghdr *nlh, struct nft_rule *r) { struct nlattr *tb[NFTA_RULE_MAX+1] = {}; @@ -343,6 +424,8 @@ int nft_rule_nlmsg_parse(const struct nlmsghdr *nlh, struct nft_rule *r) } if (tb[NFTA_RULE_EXPRESSIONS]) ret = nft_rule_parse_expr(tb[NFTA_RULE_EXPRESSIONS], r); + if (tb[NFTA_RULE_COMPAT]) + ret = nft_rule_parse_compat(tb[NFTA_RULE_COMPAT], r); r->family = nfg->nfgen_family; r->flags |= (1 << NFT_RULE_ATTR_FAMILY); -- cgit v1.2.3