summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cache.c26
-rw-r--r--src/cmd.c18
-rw-r--r--src/evaluate.c88
-rw-r--r--src/netlink.c1
-rw-r--r--src/netlink_linearize.c6
-rw-r--r--src/rule.c15
-rw-r--r--src/scanner.l47
7 files changed, 146 insertions, 55 deletions
diff --git a/src/cache.c b/src/cache.c
index c000e32c..4b797ec7 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -297,6 +297,7 @@ static unsigned int evaluate_cache_reset(struct cmd *cmd, unsigned int flags,
flags |= NFT_CACHE_TABLE;
break;
}
+ flags |= NFT_CACHE_REFRESH;
return flags;
}
@@ -1177,14 +1178,27 @@ static bool nft_cache_is_complete(struct nft_cache *cache, unsigned int flags)
return (cache->flags & flags) == flags;
}
-static bool nft_cache_needs_refresh(struct nft_cache *cache)
+static bool nft_cache_needs_refresh(struct nft_cache *cache, unsigned int flags)
{
- return cache->flags & NFT_CACHE_REFRESH;
+ return (cache->flags & NFT_CACHE_REFRESH) ||
+ (flags & NFT_CACHE_REFRESH);
}
-static bool nft_cache_is_updated(struct nft_cache *cache, uint16_t genid)
+static bool nft_cache_is_updated(struct nft_cache *cache, unsigned int flags,
+ uint16_t genid)
{
- return genid && genid == cache->genid;
+ if (!genid)
+ return false;
+
+ if (genid == cache->genid)
+ return true;
+
+ if (genid == cache->genid + 1) {
+ cache->genid++;
+ return true;
+ }
+
+ return false;
}
bool nft_cache_needs_update(struct nft_cache *cache)
@@ -1207,9 +1221,9 @@ int nft_cache_update(struct nft_ctx *nft, unsigned int flags,
replay:
ctx.seqnum = cache->seqnum++;
genid = mnl_genid_get(&ctx);
- if (!nft_cache_needs_refresh(cache) &&
+ if (!nft_cache_needs_refresh(cache, flags) &&
nft_cache_is_complete(cache, flags) &&
- nft_cache_is_updated(cache, genid))
+ nft_cache_is_updated(cache, flags, genid))
return 0;
if (cache->genid)
diff --git a/src/cmd.c b/src/cmd.c
index 14cb1b51..37d93abc 100644
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -256,7 +256,8 @@ static void nft_cmd_enoent(struct netlink_ctx *ctx, const struct cmd *cmd,
static int nft_cmd_chain_error(struct netlink_ctx *ctx, struct cmd *cmd,
struct mnl_err *err)
{
- struct chain *chain = cmd->chain;
+ struct chain *chain = cmd->chain, *existing_chain;
+ const struct table *table;
int priority;
switch (err->err) {
@@ -270,6 +271,18 @@ static int nft_cmd_chain_error(struct netlink_ctx *ctx, struct cmd *cmd,
return netlink_io_error(ctx, &chain->priority.loc,
"Chains of type \"nat\" must have a priority value above -200");
+ table = table_cache_find(&ctx->nft->cache.table_cache,
+ cmd->handle.table.name, cmd->handle.family);
+ if (table) {
+ existing_chain = chain_cache_find(table, cmd->handle.chain.name);
+ if (existing_chain && existing_chain != chain &&
+ !strcmp(existing_chain->handle.chain.name, chain->handle.chain.name))
+ return netlink_io_error(ctx, &chain->loc,
+ "Chain \"%s\" already exists in table %s '%s' with different declaration",
+ chain->handle.chain.name,
+ family2str(table->handle.family), table->handle.table.name);
+ }
+
return netlink_io_error(ctx, &chain->loc,
"Chain of type \"%s\" is not supported, perhaps kernel support is missing?",
chain->type.str);
@@ -442,6 +455,9 @@ bool nft_cmd_collapse(struct list_head *cmds)
continue;
}
+ if (cmd->expr->etype == EXPR_VARIABLE)
+ continue;
+
if (!elems) {
elems = cmd;
continue;
diff --git a/src/evaluate.c b/src/evaluate.c
index 1682ba58..227f5da8 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -775,6 +775,46 @@ static bool proto_is_dummy(const struct proto_desc *desc)
return desc == &proto_inet || desc == &proto_netdev;
}
+static int stmt_dep_conflict(struct eval_ctx *ctx, const struct stmt *nstmt)
+{
+ struct stmt *stmt;
+
+ list_for_each_entry(stmt, &ctx->rule->stmts, list) {
+ if (stmt == nstmt)
+ break;
+
+ if (stmt->ops->type != STMT_EXPRESSION ||
+ stmt->expr->etype != EXPR_RELATIONAL ||
+ stmt->expr->right->etype != EXPR_VALUE ||
+ stmt->expr->left->etype != EXPR_PAYLOAD ||
+ stmt->expr->left->etype != nstmt->expr->left->etype ||
+ stmt->expr->left->len != nstmt->expr->left->len)
+ continue;
+
+ if (stmt->expr->left->payload.desc != nstmt->expr->left->payload.desc ||
+ stmt->expr->left->payload.inner_desc != nstmt->expr->left->payload.inner_desc ||
+ stmt->expr->left->payload.base != nstmt->expr->left->payload.base ||
+ stmt->expr->left->payload.offset != nstmt->expr->left->payload.offset)
+ continue;
+
+ return stmt_binary_error(ctx, stmt, nstmt,
+ "conflicting statements");
+ }
+
+ return 0;
+}
+
+static int rule_stmt_dep_add(struct eval_ctx *ctx,
+ struct stmt *nstmt, struct stmt *stmt)
+{
+ rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
+
+ if (stmt_dep_conflict(ctx, nstmt) < 0)
+ return -1;
+
+ return 0;
+}
+
static int resolve_ll_protocol_conflict(struct eval_ctx *ctx,
const struct proto_desc *desc,
struct expr *payload)
@@ -798,7 +838,8 @@ static int resolve_ll_protocol_conflict(struct eval_ctx *ctx,
return err;
desc = payload->payload.desc;
- rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
+ if (rule_stmt_dep_add(ctx, nstmt, ctx->stmt) < 0)
+ return -1;
}
} else {
unsigned int i;
@@ -810,10 +851,6 @@ static int resolve_ll_protocol_conflict(struct eval_ctx *ctx,
}
}
- /* This payload and the existing context don't match, conflict. */
- if (pctx->protocol[base + 1].desc != NULL)
- return 1;
-
link = proto_find_num(desc, payload->payload.desc);
if (link < 0 ||
ll_conflict_resolution_gen_dependency(ctx, link, payload, &nstmt) < 0)
@@ -822,7 +859,8 @@ static int resolve_ll_protocol_conflict(struct eval_ctx *ctx,
for (i = 0; i < pctx->stacked_ll_count; i++)
payload->payload.offset += pctx->stacked_ll[i]->length;
- rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
+ if (rule_stmt_dep_add(ctx, nstmt, ctx->stmt) < 0)
+ return -1;
return 0;
}
@@ -850,7 +888,8 @@ static int __expr_evaluate_payload(struct eval_ctx *ctx, struct expr *expr)
if (payload_gen_dependency(ctx, payload, &nstmt) < 0)
return -1;
- rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
+ if (rule_stmt_dep_add(ctx, nstmt, ctx->stmt) < 0)
+ return -1;
desc = pctx->protocol[base].desc;
@@ -870,7 +909,10 @@ static int __expr_evaluate_payload(struct eval_ctx *ctx, struct expr *expr)
assert(pctx->stacked_ll_count);
payload->payload.offset += pctx->stacked_ll[0]->length;
- rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
+
+ if (rule_stmt_dep_add(ctx, nstmt, ctx->stmt) < 0)
+ return -1;
+
return 1;
}
goto check_icmp;
@@ -911,8 +953,8 @@ check_icmp:
if (payload_gen_icmp_dependency(ctx, expr, &nstmt) < 0)
return -1;
- if (nstmt)
- rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
+ if (nstmt && rule_stmt_dep_add(ctx, nstmt, ctx->stmt) < 0)
+ return -1;
return 0;
}
@@ -988,7 +1030,8 @@ static int expr_evaluate_inner(struct eval_ctx *ctx, struct expr **exprp)
if (payload_gen_inner_dependency(ctx, expr, &nstmt) < 0)
return -1;
- rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
+ if (rule_stmt_dep_add(ctx, nstmt, ctx->stmt) < 0)
+ return -1;
proto_ctx_update(pctx, PROTO_BASE_TRANSPORT_HDR, &expr->location, expr->payload.inner_desc);
}
@@ -1083,7 +1126,7 @@ static int ct_gen_nh_dependency(struct eval_ctx *ctx, struct expr *ct)
base = pctx->protocol[PROTO_BASE_NETWORK_HDR].desc;
if (base == &proto_ip)
ct->ct.nfproto = NFPROTO_IPV4;
- else if (base == &proto_ip)
+ else if (base == &proto_ip6)
ct->ct.nfproto = NFPROTO_IPV6;
if (base)
@@ -1119,7 +1162,9 @@ static int ct_gen_nh_dependency(struct eval_ctx *ctx, struct expr *ct)
relational_expr_pctx_update(pctx, dep);
nstmt = expr_stmt_alloc(&dep->location, dep);
- rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
+
+ if (rule_stmt_dep_add(ctx, nstmt, ctx->stmt) < 0)
+ return -1;
return 0;
}
@@ -2061,6 +2106,7 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
mappings->set_flags |= NFT_SET_MAP;
switch (map->mappings->etype) {
+ case EXPR_VARIABLE:
case EXPR_SET:
if (ctx->ectx.key && ctx->ectx.key->etype == EXPR_CONCAT) {
key = expr_clone(ctx->ectx.key);
@@ -2104,6 +2150,11 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
if (expr_evaluate(ctx, &map->mappings->set->init) < 0)
return -1;
+ if (map->mappings->set->init->etype != EXPR_SET) {
+ return expr_error(ctx->msgs, map->mappings->set->init,
+ "Expression is not a map");
+ }
+
if (set_is_interval(map->mappings->set->init->set_flags) &&
!(map->mappings->set->init->set_flags & NFT_SET_CONCAT) &&
interval_set_eval(ctx, ctx->set, map->mappings->set->init) < 0)
@@ -4576,6 +4627,7 @@ static int stmt_evaluate_objref_map(struct eval_ctx *ctx, struct stmt *stmt)
mappings->set_flags |= NFT_SET_OBJECT;
switch (map->mappings->etype) {
+ case EXPR_VARIABLE:
case EXPR_SET:
key = constant_expr_alloc(&stmt->location,
ctx->ectx.dtype,
@@ -4595,6 +4647,11 @@ static int stmt_evaluate_objref_map(struct eval_ctx *ctx, struct stmt *stmt)
if (expr_evaluate(ctx, &map->mappings->set->init) < 0)
return -1;
+ if (map->mappings->set->init->etype != EXPR_SET) {
+ return expr_error(ctx->msgs, map->mappings->set->init,
+ "Expression is not a map");
+ }
+
if (set_is_interval(map->mappings->set->init->set_flags) &&
!(map->mappings->set->init->set_flags & NFT_SET_CONCAT) &&
interval_set_eval(ctx, ctx->set, map->mappings->set->init) < 0)
@@ -4615,8 +4672,9 @@ static int stmt_evaluate_objref_map(struct eval_ctx *ctx, struct stmt *stmt)
"Expression is not a map with objects");
break;
default:
- BUG("invalid mapping expression %s\n",
- expr_name(map->mappings));
+ return expr_binary_error(ctx->msgs, map->mappings, map->map,
+ "invalid mapping expression %s",
+ expr_name(map->mappings));
}
if (!datatype_compatible(map->mappings->set->key->dtype, map->map->dtype))
diff --git a/src/netlink.c b/src/netlink.c
index 0088b742..efb0b699 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -2096,6 +2096,7 @@ restart:
/* Skip unknown and filtered expressions */
desc = lhs->payload.desc;
if (lhs->dtype == &invalid_type ||
+ lhs->payload.tmpl == &proto_unknown_template ||
desc->checksum_key == payload_hdr_field(lhs) ||
desc->format.filter & (1 << payload_hdr_field(lhs))) {
expr_free(lhs);
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 6204d8fd..de9e975f 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -1592,11 +1592,11 @@ static void netlink_gen_map_stmt(struct netlink_linearize_ctx *ctx,
sreg_key = get_register(ctx, stmt->map.key->key);
netlink_gen_expr(ctx, stmt->map.key->key, sreg_key);
- sreg_data = get_register(ctx, stmt->map.data);
- netlink_gen_expr(ctx, stmt->map.data, sreg_data);
+ sreg_data = get_register(ctx, stmt->map.data->key);
+ netlink_gen_expr(ctx, stmt->map.data->key, sreg_data);
release_register(ctx, stmt->map.key->key);
- release_register(ctx, stmt->map.data);
+ release_register(ctx, stmt->map.data->key);
nle = alloc_nft_expr("dynset");
netlink_put_register(nle, NFTNL_EXPR_DYNSET_SREG_KEY, sreg_key);
diff --git a/src/rule.c b/src/rule.c
index 65ff0fbb..545f9b2b 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -2107,12 +2107,15 @@ static void flowtable_print_declaration(const struct flowtable *flowtable,
if (nft_output_handle(octx))
nft_print(octx, " # handle %" PRIu64, flowtable->handle.handle.id);
nft_print(octx, "%s", opts->nl);
- nft_print(octx, "%s%shook %s priority %s%s",
- opts->tab, opts->tab,
- hooknum2str(NFPROTO_NETDEV, flowtable->hook.num),
- prio2str(octx, priobuf, sizeof(priobuf), NFPROTO_NETDEV,
- flowtable->hook.num, flowtable->priority.expr),
- opts->stmt_separator);
+
+ if (flowtable->priority.expr) {
+ nft_print(octx, "%s%shook %s priority %s%s",
+ opts->tab, opts->tab,
+ hooknum2str(NFPROTO_NETDEV, flowtable->hook.num),
+ prio2str(octx, priobuf, sizeof(priobuf), NFPROTO_NETDEV,
+ flowtable->hook.num, flowtable->priority.expr),
+ opts->stmt_separator);
+ }
if (flowtable->dev_array_len > 0) {
nft_print(octx, "%s%sdevices = { ", opts->tab, opts->tab);
diff --git a/src/scanner.l b/src/scanner.l
index e4d20e69..96c505bc 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -132,48 +132,47 @@ slash \/
timestring ([0-9]+d)?([0-9]+h)?([0-9]+m)?([0-9]+s)?([0-9]+ms)?
hex4 ([[:xdigit:]]{1,4})
+rfc4291_broader (((:{hex4}){2})|(:{ip4addr}))
v680 (({hex4}:){7}{hex4})
-v670 ((:)((:{hex4}){7}))
-v671 ((({hex4}:){1})((:{hex4}){6}))
-v672 ((({hex4}:){2})((:{hex4}){5}))
-v673 ((({hex4}:){3})((:{hex4}){4}))
-v674 ((({hex4}:){4})((:{hex4}){3}))
-v675 ((({hex4}:){5})((:{hex4}){2}))
+v670 ((:)((:{hex4}){5}){rfc4291_broader})
+v671 ((({hex4}:){1})((:{hex4}){4}){rfc4291_broader})
+v672 ((({hex4}:){2})((:{hex4}){3}){rfc4291_broader})
+v673 ((({hex4}:){3})((:{hex4}){2}){rfc4291_broader})
+v674 ((({hex4}:){4})((:{hex4}){1}){rfc4291_broader})
+v675 ((({hex4}:){5}){rfc4291_broader})
v676 ((({hex4}:){6})(:{hex4}{1}))
v677 ((({hex4}:){7})(:))
v67 ({v670}|{v671}|{v672}|{v673}|{v674}|{v675}|{v676}|{v677})
-v660 ((:)((:{hex4}){6}))
-v661 ((({hex4}:){1})((:{hex4}){5}))
-v662 ((({hex4}:){2})((:{hex4}){4}))
-v663 ((({hex4}:){3})((:{hex4}){3}))
-v664 ((({hex4}:){4})((:{hex4}){2}))
+v660 ((:)((:{hex4}){4}){rfc4291_broader})
+v661 ((({hex4}:){1})((:{hex4}){3}){rfc4291_broader})
+v662 ((({hex4}:){2})((:{hex4}){2}){rfc4291_broader})
+v663 ((({hex4}:){3})((:{hex4}){1}){rfc4291_broader})
+v664 ((({hex4}:){4}){rfc4291_broader})
v665 ((({hex4}:){5})((:{hex4}){1}))
v666 ((({hex4}:){6})(:))
v66 ({v660}|{v661}|{v662}|{v663}|{v664}|{v665}|{v666})
-v650 ((:)((:{hex4}){5}))
-v651 ((({hex4}:){1})((:{hex4}){4}))
-v652 ((({hex4}:){2})((:{hex4}){3}))
-v653 ((({hex4}:){3})((:{hex4}){2}))
+v650 ((:)((:{hex4}){3}){rfc4291_broader})
+v651 ((({hex4}:){1})((:{hex4}){2}){rfc4291_broader})
+v652 ((({hex4}:){2})((:{hex4}){1}){rfc4291_broader})
+v653 ((({hex4}:){3}){rfc4291_broader})
v654 ((({hex4}:){4})(:{hex4}{1}))
v655 ((({hex4}:){5})(:))
v65 ({v650}|{v651}|{v652}|{v653}|{v654}|{v655})
-v640 ((:)((:{hex4}){4}))
-v641 ((({hex4}:){1})((:{hex4}){3}))
-v642 ((({hex4}:){2})((:{hex4}){2}))
+v640 ((:)((:{hex4}){2}){rfc4291_broader})
+v641 ((({hex4}:){1})((:{hex4}){1}){rfc4291_broader})
+v642 ((({hex4}:){2}){rfc4291_broader})
v643 ((({hex4}:){3})((:{hex4}){1}))
v644 ((({hex4}:){4})(:))
v64 ({v640}|{v641}|{v642}|{v643}|{v644})
-v630 ((:)((:{hex4}){3}))
-v631 ((({hex4}:){1})((:{hex4}){2}))
+v630 ((:)((:{hex4}){1}){rfc4291_broader})
+v631 ((({hex4}:){1}){rfc4291_broader})
v632 ((({hex4}:){2})((:{hex4}){1}))
v633 ((({hex4}:){3})(:))
v63 ({v630}|{v631}|{v632}|{v633})
-v620 ((:)((:{hex4}){2}))
-v620_rfc4291 ((:)(:{ip4addr}))
+v620 ((:){rfc4291_broader})
v621 ((({hex4}:){1})((:{hex4}){1}))
v622 ((({hex4}:){2})(:))
-v62_rfc4291 ((:)(:[fF]{4})(:{ip4addr}))
-v62 ({v620}|{v621}|{v622}|{v62_rfc4291}|{v620_rfc4291})
+v62 ({v620}|{v621}|{v622})
v610 ((:)(:{hex4}{1}))
v611 ((({hex4}:){1})(:))
v61 ({v610}|{v611})