From 259c0e74e97b4d769044a399992802c50ff43ce2 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 12 Apr 2015 20:17:52 +0100 Subject: dynset: support expression templates Support expression templates for the dynset expression for dynamic expression instantiation. Signed-off-by: Patrick McHardy --- src/expr/dynset.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'src/expr/dynset.c') diff --git a/src/expr/dynset.c b/src/expr/dynset.c index 034ef32..e3fecf5 100644 --- a/src/expr/dynset.c +++ b/src/expr/dynset.c @@ -31,6 +31,7 @@ struct nft_expr_dynset { enum nft_registers sreg_data; enum nft_dynset_ops op; uint64_t timeout; + struct nft_rule_expr *expr; char set_name[IFNAMSIZ]; uint32_t set_id; }; @@ -61,6 +62,9 @@ nft_rule_expr_dynset_set(struct nft_rule_expr *e, uint16_t type, case NFT_EXPR_DYNSET_SET_ID: dynset->set_id = *((uint32_t *)data); break; + case NFT_EXPR_DYNSET_EXPR: + dynset->expr = (void *)data; + break; default: return -1; } @@ -90,6 +94,8 @@ nft_rule_expr_dynset_get(const struct nft_rule_expr *e, uint16_t type, return dynset->set_name; case NFT_EXPR_DYNSET_SET_ID: return &dynset->set_id; + case NFT_EXPR_DYNSET_EXPR: + return dynset->expr; } return NULL; } @@ -118,6 +124,10 @@ static int nft_rule_expr_dynset_cb(const struct nlattr *attr, void *data) if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) abi_breakage(); break; + case NFTA_DYNSET_EXPR: + if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) + abi_breakage(); + break; } tb[type] = attr; @@ -128,6 +138,7 @@ static void nft_rule_expr_dynset_build(struct nlmsghdr *nlh, struct nft_rule_expr *e) { struct nft_expr_dynset *dynset = nft_expr_data(e); + struct nlattr *nest; if (e->flags & (1 << NFT_EXPR_DYNSET_SREG_KEY)) mnl_attr_put_u32(nlh, NFTA_DYNSET_SREG_KEY, htonl(dynset->sreg_key)); @@ -141,6 +152,11 @@ nft_rule_expr_dynset_build(struct nlmsghdr *nlh, struct nft_rule_expr *e) mnl_attr_put_strz(nlh, NFTA_DYNSET_SET_NAME, dynset->set_name); if (e->flags & (1 << NFT_EXPR_DYNSET_SET_ID)) mnl_attr_put_u32(nlh, NFTA_DYNSET_SET_ID, htonl(dynset->set_id)); + if (e->flags & (1 << NFT_EXPR_DYNSET_EXPR)) { + nest = mnl_attr_nest_start(nlh, NFTA_DYNSET_EXPR); + nft_rule_expr_build_payload(nlh, dynset->expr); + mnl_attr_nest_end(nlh, nest); + } } static int @@ -177,6 +193,12 @@ nft_rule_expr_dynset_parse(struct nft_rule_expr *e, struct nlattr *attr) dynset->set_id = ntohl(mnl_attr_get_u32(tb[NFTA_DYNSET_SET_ID])); e->flags |= (1 << NFT_EXPR_DYNSET_SET_ID); } + if (tb[NFTA_DYNSET_EXPR]) { + e->flags |= (1 << NFT_EXPR_DYNSET_EXPR); + dynset->expr = nft_rule_expr_parse(tb[NFTA_DYNSET_EXPR]); + if (dynset->expr == NULL) + return -1; + } return ret; } @@ -288,6 +310,7 @@ nft_rule_expr_dynset_snprintf_default(char *buf, size_t size, struct nft_rule_expr *e) { struct nft_expr_dynset *dynset = nft_expr_data(e); + struct nft_rule_expr *expr; int len = size, offset = 0, ret; ret = snprintf(buf, len, "%s reg_key %u set %s ", @@ -303,6 +326,21 @@ nft_rule_expr_dynset_snprintf_default(char *buf, size_t size, dynset->timeout); SNPRINTF_BUFFER_SIZE(ret, size, len, offset); } + if (e->flags & (1 << NFT_EXPR_DYNSET_EXPR)) { + expr = dynset->expr; + ret = snprintf(buf+offset, len, "expr [ %s ", + expr->ops->name); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + + ret = nft_rule_expr_snprintf(buf+offset, len, expr, + NFT_OUTPUT_DEFAULT, + NFT_OF_EVENT_ANY); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + + ret = snprintf(buf+offset, len, "] "); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + } + return offset; } -- cgit v1.2.3