diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cache.c | 26 | ||||
-rw-r--r-- | src/cmd.c | 18 | ||||
-rw-r--r-- | src/evaluate.c | 88 | ||||
-rw-r--r-- | src/netlink.c | 1 | ||||
-rw-r--r-- | src/netlink_linearize.c | 6 | ||||
-rw-r--r-- | src/rule.c | 15 | ||||
-rw-r--r-- | src/scanner.l | 47 |
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) @@ -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); @@ -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}) |