--- /dev/null
+/*
+ * Copyright (c) 2019 Pablo Neira Ayuso <pablo@netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 (or any
+ * later) as published by the Free Software Foundation.
+ */
+
+#include <expression.h>
+#include <statement.h>
+#include <rule.h>
+#include <erec.h>
+#include <utils.h>
+
+static unsigned int evaluate_cache_add(struct cmd *cmd)
+{
+ unsigned int completeness = CMD_INVALID;
+
+ switch (cmd->obj) {
+ case CMD_OBJ_SETELEM:
+ case CMD_OBJ_SET:
+ case CMD_OBJ_CHAIN:
+ case CMD_OBJ_FLOWTABLE:
+ completeness = cmd->op;
+ break;
+ case CMD_OBJ_RULE:
+ /* XXX index is set to zero unless this handle_merge() call is
+ * invoked, this handle_merge() call is done from the
+ * evaluation, which is too late.
+ */
+ handle_merge(&cmd->rule->handle, &cmd->handle);
+
+ if (cmd->rule->handle.index.id)
+ completeness = CMD_LIST;
+ break;
+ default:
+ break;
+ }
+
+ return completeness;
+}
+
+static unsigned int evaluate_cache_del(struct cmd *cmd)
+{
+ unsigned int completeness = CMD_INVALID;
+
+ switch (cmd->obj) {
+ case CMD_OBJ_SETELEM:
+ completeness = cmd->op;
+ break;
+ default:
+ break;
+ }
+
+ return completeness;
+}
+
+static unsigned int evaluate_cache_flush(struct cmd *cmd)
+{
+ unsigned int completeness = CMD_INVALID;
+
+ switch (cmd->obj) {
+ case CMD_OBJ_SET:
+ case CMD_OBJ_MAP:
+ case CMD_OBJ_METER:
+ completeness = cmd->op;
+ break;
+ default:
+ break;
+ }
+
+ return completeness;
+}
+
+static unsigned int evaluate_cache_rename(struct cmd *cmd)
+{
+ unsigned int completeness = CMD_INVALID;
+
+ switch (cmd->obj) {
+ case CMD_OBJ_CHAIN:
+ completeness = cmd->op;
+ break;
+ default:
+ break;
+ }
+
+ return completeness;
+}
+
+int cache_evaluate(struct nft_ctx *nft, struct list_head *cmds)
+{
+ unsigned int echo_completeness = CMD_INVALID;
+ unsigned int completeness = CMD_INVALID;
+ struct cmd *cmd;
+
+ list_for_each_entry(cmd, cmds, list) {
+ switch (cmd->op) {
+ case CMD_ADD:
+ case CMD_INSERT:
+ case CMD_REPLACE:
+ if (nft_output_echo(&nft->output))
+ echo_completeness = cmd->op;
+
+ /* Fall through */
+ case CMD_CREATE:
+ completeness = evaluate_cache_add(cmd);
+ break;
+ case CMD_DELETE:
+ completeness = evaluate_cache_del(cmd);
+ break;
+ case CMD_GET:
+ case CMD_LIST:
+ case CMD_RESET:
+ case CMD_EXPORT:
+ case CMD_MONITOR:
+ completeness = cmd->op;
+ break;
+ case CMD_FLUSH:
+ completeness = evaluate_cache_flush(cmd);
+ break;
+ case CMD_RENAME:
+ completeness = evaluate_cache_rename(cmd);
+ break;
+ case CMD_DESCRIBE:
+ case CMD_IMPORT:
+ break;
+ default:
+ break;
+ }
+ }
+
+ return max(completeness, echo_completeness);
+}
struct table *table;
struct set *set;
struct expr *new;
- int ret;
switch ((*expr)->symtype) {
case SYMBOL_VALUE:
}
break;
case SYMBOL_SET:
- ret = cache_update(ctx->nft, ctx->cmd->op, ctx->msgs);
- if (ret < 0)
- return ret;
-
table = table_lookup_global(ctx);
if (table == NULL)
return table_not_found(ctx);
struct chain *chain;
uint64_t index = 0;
struct rule *r;
- int ret;
-
- /* update cache with CMD_LIST so that rules are fetched, too */
- ret = cache_update(ctx->nft, CMD_LIST, ctx->msgs);
- if (ret < 0)
- return ret;
table = table_lookup(&rule->handle, &ctx->nft->cache);
if (!table)
static int cmd_evaluate_add(struct eval_ctx *ctx, struct cmd *cmd)
{
- int ret;
-
switch (cmd->obj) {
case CMD_OBJ_SETELEM:
- ret = cache_update(ctx->nft, cmd->op, ctx->msgs);
- if (ret < 0)
- return ret;
-
return setelem_evaluate(ctx, &cmd->expr);
case CMD_OBJ_SET:
- ret = cache_update(ctx->nft, cmd->op, ctx->msgs);
- if (ret < 0)
- return ret;
-
handle_merge(&cmd->set->handle, &cmd->handle);
return set_evaluate(ctx, cmd->set);
case CMD_OBJ_RULE:
handle_merge(&cmd->rule->handle, &cmd->handle);
return rule_evaluate(ctx, cmd->rule);
case CMD_OBJ_CHAIN:
- ret = cache_update(ctx->nft, cmd->op, ctx->msgs);
- if (ret < 0)
- return ret;
-
return chain_evaluate(ctx, cmd->chain);
case CMD_OBJ_TABLE:
return table_evaluate(ctx, cmd->table);
case CMD_OBJ_FLOWTABLE:
- ret = cache_update(ctx->nft, cmd->op, ctx->msgs);
- if (ret < 0)
- return ret;
-
handle_merge(&cmd->flowtable->handle, &cmd->handle);
return flowtable_evaluate(ctx, cmd->flowtable);
case CMD_OBJ_COUNTER:
static int cmd_evaluate_delete(struct eval_ctx *ctx, struct cmd *cmd)
{
- int ret;
-
switch (cmd->obj) {
case CMD_OBJ_SETELEM:
- ret = cache_update(ctx->nft, cmd->op, ctx->msgs);
- if (ret < 0)
- return ret;
-
return setelem_evaluate(ctx, &cmd->expr);
case CMD_OBJ_SET:
case CMD_OBJ_RULE:
{
struct table *table;
struct set *set;
- int ret;
-
- ret = cache_update(ctx->nft, cmd->op, ctx->msgs);
- if (ret < 0)
- return ret;
switch (cmd->obj) {
case CMD_OBJ_SETELEM:
{
struct table *table;
struct set *set;
- int ret;
-
- ret = cache_update(ctx->nft, cmd->op, ctx->msgs);
- if (ret < 0)
- return ret;
switch (cmd->obj) {
case CMD_OBJ_TABLE:
static int cmd_evaluate_reset(struct eval_ctx *ctx, struct cmd *cmd)
{
- int ret;
-
- ret = cache_update(ctx->nft, cmd->op, ctx->msgs);
- if (ret < 0)
- return ret;
-
switch (cmd->obj) {
case CMD_OBJ_COUNTER:
case CMD_OBJ_QUOTA:
{
struct table *table;
struct set *set;
- int ret;
switch (cmd->obj) {
case CMD_OBJ_RULESET:
/* Chains don't hold sets */
break;
case CMD_OBJ_SET:
- ret = cache_update(ctx->nft, cmd->op, ctx->msgs);
- if (ret < 0)
- return ret;
-
table = table_lookup(&cmd->handle, &ctx->nft->cache);
if (table == NULL)
return table_not_found(ctx);
return 0;
case CMD_OBJ_MAP:
- ret = cache_update(ctx->nft, cmd->op, ctx->msgs);
- if (ret < 0)
- return ret;
-
table = table_lookup(&cmd->handle, &ctx->nft->cache);
if (table == NULL)
return table_not_found(ctx);
return 0;
case CMD_OBJ_METER:
- ret = cache_update(ctx->nft, cmd->op, ctx->msgs);
- if (ret < 0)
- return ret;
-
table = table_lookup(&cmd->handle, &ctx->nft->cache);
if (table == NULL)
return table_not_found(ctx);
static int cmd_evaluate_rename(struct eval_ctx *ctx, struct cmd *cmd)
{
struct table *table;
- int ret;
switch (cmd->obj) {
case CMD_OBJ_CHAIN:
- ret = cache_update(ctx->nft, cmd->op, ctx->msgs);
- if (ret < 0)
- return ret;
-
table = table_lookup(&ctx->cmd->handle, &ctx->nft->cache);
if (table == NULL)
return table_not_found(ctx);
static int cmd_evaluate_monitor(struct eval_ctx *ctx, struct cmd *cmd)
{
uint32_t event;
- int ret;
-
- ret = cache_update(ctx->nft, cmd->op, ctx->msgs);
- if (ret < 0)
- return ret;
if (cmd->monitor->event == NULL)
event = CMD_MONITOR_EVENT_ANY;
return cmd_error(ctx, &cmd->location,
"JSON export is no longer supported, use 'nft -j list ruleset' instead");
- return cache_update(ctx->nft, cmd->op, ctx->msgs);
+ return 0;
}
static int cmd_evaluate_import(struct eval_ctx *ctx, struct cmd *cmd)