@@ -309,6 +309,7 @@ struct expr {
enum nft_ng_types type;
uint32_t mod;
uint32_t offset;
+ struct expr *ng_map;
} numgen;
struct {
/* EXPR_HASH */
@@ -1382,6 +1382,8 @@ enum nft_trace_types {
* @NFTA_NG_MODULUS: maximum counter value (NLA_U32)
* @NFTA_NG_TYPE: operation type (NLA_U32)
* @NFTA_NG_OFFSET: offset to be added to the counter (NLA_U32)
+ * @NFTA_NG_SET_NAME: name of the map to lookup (NLA_STRING)
+ * @NFTA_NG_SET_ID: if of the map (NLA_U32)
*/
enum nft_ng_attributes {
NFTA_NG_UNSPEC,
@@ -1389,6 +1391,8 @@ enum nft_ng_attributes {
NFTA_NG_MODULUS,
NFTA_NG_TYPE,
NFTA_NG_OFFSET,
+ NFTA_NG_SET_NAME,
+ NFTA_NG_SET_ID,
__NFTA_NG_MAX
};
#define NFTA_NG_MAX (__NFTA_NG_MAX - 1)
@@ -3,6 +3,6 @@
extern struct expr *numgen_expr_alloc(const struct location *loc,
enum nft_ng_types type, uint32_t until,
- uint32_t offset);
+ uint32_t offset, struct expr *mappings);
#endif /* NFTABLES_NUMGEN_H */
@@ -945,7 +945,8 @@ static void map_expr_print(const struct expr *expr, struct output_ctx *octx)
static void map_expr_clone(struct expr *new, const struct expr *expr)
{
- new->map = expr_clone(expr->map);
+ if (expr->map)
+ new->map = expr_clone(expr->map);
new->mappings = expr_clone(expr->mappings);
}
@@ -668,13 +668,27 @@ static void netlink_parse_numgen(struct netlink_parse_ctx *ctx,
{
enum nft_registers dreg;
uint32_t type, until, offset;
- struct expr *expr;
+ const char *name;
+ struct expr *expr, *right, *map_expr = NULL;
+ struct set *map;
type = nftnl_expr_get_u32(nle, NFTNL_EXPR_NG_TYPE);
until = nftnl_expr_get_u32(nle, NFTNL_EXPR_NG_MODULUS);
offset = nftnl_expr_get_u32(nle, NFTNL_EXPR_NG_OFFSET);
- expr = numgen_expr_alloc(loc, type, until, offset);
+ name = nftnl_expr_get_str(nle, NFTNL_EXPR_NG_SET_NAME);
+ if (name != NULL) {
+ map = set_lookup(ctx->table, name);
+ if (map == NULL) {
+ return netlink_error(ctx, loc,
+ "Unknown map '%s' in numgen expression",
+ name);
+ }
+ right = set_ref_expr_alloc(loc, map);
+ map_expr = map_expr_alloc(loc, NULL, right);
+ }
+
+ expr = numgen_expr_alloc(loc, type, until, offset, map_expr);
dreg = netlink_parse_register(nle, NFTNL_EXPR_NG_DREG);
netlink_set_register(ctx, dreg, expr);
}
@@ -218,6 +218,14 @@ static void netlink_gen_numgen(struct netlink_linearize_ctx *ctx,
nftnl_expr_set_u32(nle, NFTNL_EXPR_NG_TYPE, expr->numgen.type);
nftnl_expr_set_u32(nle, NFTNL_EXPR_NG_MODULUS, expr->numgen.mod);
nftnl_expr_set_u32(nle, NFTNL_EXPR_NG_OFFSET, expr->numgen.offset);
+
+ if (expr->numgen.ng_map) {
+ nftnl_expr_set_str(nle, NFTNL_EXPR_NG_SET_NAME,
+ expr->numgen.ng_map->mappings->identifier);
+ nftnl_expr_set_u32(nle, NFTNL_EXPR_NG_SET_ID,
+ expr->numgen.ng_map->mappings->set->handle.set_id);
+ }
+
nftnl_rule_add_expr(ctx->nlr, nle);
}
@@ -35,13 +35,18 @@ static void numgen_expr_print(const struct expr *expr, struct output_ctx *octx)
expr->numgen.mod);
if (expr->numgen.offset)
nft_print(octx, " offset %u", expr->numgen.offset);
+ if (expr->numgen.ng_map) {
+ nft_print(octx, " ");
+ expr_print(expr->numgen.ng_map->mappings, octx);
+ }
}
static bool numgen_expr_cmp(const struct expr *e1, const struct expr *e2)
{
return e1->numgen.type == e2->numgen.type &&
e1->numgen.mod == e2->numgen.mod &&
- e1->numgen.offset == e2->numgen.offset;
+ e1->numgen.offset == e2->numgen.offset &&
+ expr_cmp(e1->numgen.ng_map, e2->numgen.ng_map);
}
static void numgen_expr_clone(struct expr *new, const struct expr *expr)
@@ -49,6 +54,8 @@ static void numgen_expr_clone(struct expr *new, const struct expr *expr)
new->numgen.type = expr->numgen.type;
new->numgen.mod = expr->numgen.mod;
new->numgen.offset = expr->numgen.offset;
+ if (expr->numgen.ng_map)
+ new->numgen.ng_map = expr_clone(expr->numgen.ng_map);
}
static const struct expr_ops numgen_expr_ops = {
@@ -61,7 +68,7 @@ static const struct expr_ops numgen_expr_ops = {
struct expr *numgen_expr_alloc(const struct location *loc,
enum nft_ng_types type, uint32_t mod,
- uint32_t offset)
+ uint32_t offset, struct expr *mappings)
{
struct expr *expr;
@@ -70,6 +77,8 @@ struct expr *numgen_expr_alloc(const struct location *loc,
expr->numgen.type = type;
expr->numgen.mod = mod;
expr->numgen.offset = offset;
+ if (mappings)
+ expr->numgen.ng_map = mappings;
return expr;
}
@@ -660,8 +660,8 @@ int nft_lex(void *, void *, void *);
%type <expr> arp_hdr_expr
%destructor { expr_free($$); } arp_hdr_expr
%type <val> arp_hdr_field
-%type <expr> ip_hdr_expr icmp_hdr_expr numgen_expr hash_expr
-%destructor { expr_free($$); } ip_hdr_expr icmp_hdr_expr numgen_expr hash_expr
+%type <expr> ip_hdr_expr icmp_hdr_expr numgen_expr numgen_map_expr hash_expr
+%destructor { expr_free($$); } ip_hdr_expr icmp_hdr_expr numgen_expr numgen_map_expr hash_expr
%type <val> ip_hdr_field icmp_hdr_field
%type <expr> ip6_hdr_expr icmp6_hdr_expr
%destructor { expr_free($$); } ip6_hdr_expr icmp6_hdr_expr
@@ -3509,12 +3509,20 @@ numgen_type : INC { $$ = NFT_NG_INCREMENTAL; }
| RANDOM { $$ = NFT_NG_RANDOM; }
;
-numgen_expr : NUMGEN numgen_type MOD NUM offset_opt
+numgen_map_expr : /* empty */ { $$ = NULL; }
+ | symbol_expr
{
- $$ = numgen_expr_alloc(&@$, $2, $4, $5);
+ $$ = map_expr_alloc(&@$, NULL, $1);
+ $$->flags |= NFT_SET_OBJECT;
}
;
+numgen_expr : NUMGEN numgen_type MOD NUM offset_opt numgen_map_expr
+ {
+ $$ = numgen_expr_alloc(&@$, $2, $4, $5, $6);
+ }
+ ;
+
hash_expr : JHASH expr MOD NUM SEED NUM offset_opt
{
$$ = hash_expr_alloc(&@$, $4, true, $6, $7, NFT_HASH_JENKINS);
This patch introduces a map as a numgen attribute, which permits to lookup a value based on the numgen result as the key. This approach only supports named maps. Signed-off-by: Laura Garcia Liebana <nevola@gmail.com> --- include/expression.h | 1 + include/linux/netfilter/nf_tables.h | 4 ++++ include/numgen.h | 2 +- src/expression.c | 3 ++- src/netlink_delinearize.c | 18 ++++++++++++++++-- src/netlink_linearize.c | 8 ++++++++ src/numgen.c | 13 +++++++++++-- src/parser_bison.y | 16 ++++++++++++---- 8 files changed, 55 insertions(+), 10 deletions(-)