diff options
-rw-r--r-- | include/rule.h | 3 | ||||
-rw-r--r-- | src/cli.c | 1 | ||||
-rw-r--r-- | src/evaluate.c | 6 | ||||
-rw-r--r-- | src/main.c | 2 | ||||
-rw-r--r-- | src/rule.c | 103 |
5 files changed, 87 insertions, 28 deletions
diff --git a/include/rule.h b/include/rule.h index 3c915756..adff92fb 100644 --- a/include/rule.h +++ b/include/rule.h @@ -383,4 +383,7 @@ extern struct error_record *rule_postprocess(struct rule *rule); struct netlink_ctx; extern int do_command(struct netlink_ctx *ctx, struct cmd *cmd); +extern int cache_update(enum cmd_ops cmd, struct list_head *msgs); +extern void cache_release(void); + #endif /* NFTABLES_RULE_H */ @@ -124,6 +124,7 @@ static void cli_complete(char *line) nft_run(scanner, state, &msgs); erec_print_list(stdout, &msgs); xfree(line); + cache_release(); iface_cache_release(); } diff --git a/src/evaluate.c b/src/evaluate.c index 0bf4fecb..018d1b98 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -2005,6 +2005,12 @@ static int cmd_evaluate_monitor(struct eval_ctx *ctx, struct cmd *cmd) int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd) { + int ret; + + ret = cache_update(cmd->op, ctx->msgs); + if (ret < 0) + return ret; + #ifdef DEBUG if (debug_level & DEBUG_EVALUATION) { struct error_record *erec; @@ -182,7 +182,6 @@ static int nft_netlink(struct parser_state *state, struct list_head *msgs) bool batch_supported = netlink_batch_supported(); int ret = 0; - netlink_genid_get(); mnl_batch_init(); batch_seqnum = mnl_batch_begin(); @@ -366,6 +365,7 @@ out: scanner_destroy(scanner); erec_print_list(stderr, &msgs); xfree(buf); + cache_release(); iface_cache_release(); return rc; @@ -53,6 +53,73 @@ void handle_merge(struct handle *dst, const struct handle *src) dst->comment = xstrdup(src->comment); } +static LIST_HEAD(table_list); + +static int cache_init_tables(struct netlink_ctx *ctx, struct handle *h) +{ + int ret; + + ret = netlink_list_tables(ctx, h, &internal_location); + if (ret < 0) + return -1; + + list_splice_tail_init(&ctx->list, &table_list); + return 0; +} + +static int cache_init(enum cmd_ops cmd, struct list_head *msgs) +{ + struct handle handle = { + .family = NFPROTO_UNSPEC, + }; + struct netlink_ctx ctx; + int ret; + + memset(&ctx, 0, sizeof(ctx)); + init_list_head(&ctx.list); + ctx.msgs = msgs; + + ret = cache_init_tables(&ctx, &handle); + if (ret < 0) + return ret; + + return 0; +} + +static bool cache_initialized; + +int cache_update(enum cmd_ops cmd, struct list_head *msgs) +{ + int ret; + + if (cache_initialized) + return 0; +replay: + netlink_genid_get(); + ret = cache_init(cmd, msgs); + if (ret < 0) { + if (errno == EINTR) { + netlink_restart(); + goto replay; + } + cache_release(); + return -1; + } + cache_initialized = true; + return 0; +} + +void cache_release(void) +{ + struct table *table, *next; + + list_for_each_entry_safe(table, next, &table_list, list) { + list_del(&table->list); + table_free(table); + } + cache_initialized = false; +} + struct set *set_alloc(const struct location *loc) { struct set *set; @@ -535,8 +602,6 @@ void table_free(struct table *table) xfree(table); } -static LIST_HEAD(table_list); - void table_add_hash(struct table *table) { list_add_tail(&table->list, &table_list); @@ -864,8 +929,6 @@ static int do_list_table(struct netlink_ctx *ctx, struct cmd *cmd, struct rule *rule, *nrule; struct chain *chain; - if (netlink_get_table(ctx, &cmd->handle, &cmd->location, table) < 0) - goto err; if (do_list_sets(ctx, &cmd->location, table) < 0) goto err; if (netlink_list_chains(ctx, &cmd->handle, &cmd->location) < 0) @@ -895,25 +958,19 @@ err: static int do_list_ruleset(struct netlink_ctx *ctx, struct cmd *cmd) { - struct table *table, *next; - LIST_HEAD(tables); - - if (netlink_list_tables(ctx, &cmd->handle, &cmd->location) < 0) - return -1; - - list_splice_tail_init(&ctx->list, &tables); + unsigned int family = cmd->handle.family; + struct table *table; - list_for_each_entry_safe(table, next, &tables, list) { - table_add_hash(table); + list_for_each_entry(table, &table_list, list) { + if (family != NFPROTO_UNSPEC && + table->handle.family != family) + continue; cmd->handle.family = table->handle.family; cmd->handle.table = xstrdup(table->handle.table); if (do_list_table(ctx, cmd, table) < 0) return -1; - - list_del(&table->list); - table_free(table); } return 0; @@ -923,10 +980,7 @@ static int do_list_tables(struct netlink_ctx *ctx, struct cmd *cmd) { struct table *table; - if (netlink_list_tables(ctx, &cmd->handle, &cmd->location) < 0) - return -1; - - list_for_each_entry(table, &ctx->list, list) + list_for_each_entry(table, &table_list, list) printf("table %s %s\n", family2str(table->handle.family), table->handle.table); @@ -1034,7 +1088,7 @@ static int do_command_rename(struct netlink_ctx *ctx, struct cmd *cmd) static int do_command_monitor(struct netlink_ctx *ctx, struct cmd *cmd) { - struct table *t, *nt; + struct table *t; struct set *s, *ns; struct netlink_ctx set_ctx; LIST_HEAD(msgs); @@ -1057,10 +1111,7 @@ static int do_command_monitor(struct netlink_ctx *ctx, struct cmd *cmd) init_list_head(&msgs); set_ctx.msgs = &msgs; - if (netlink_list_tables(ctx, &cmd->handle, &cmd->location) < 0) - return -1; - - list_for_each_entry_safe(t, nt, &ctx->list, list) { + list_for_each_entry(t, &table_list, list) { set_handle.family = t->handle.family; set_handle.table = t->handle.table; @@ -1074,8 +1125,6 @@ static int do_command_monitor(struct netlink_ctx *ctx, struct cmd *cmd) s->init = set_expr_alloc(&cmd->location); set_add_hash(s, t); } - - table_add_hash(t); } } |