From 09f81768090ffea1dbb0362950b0d5414c609436 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 4 Jul 2014 12:24:46 +0200 Subject: mnl: check for NLM_F_DUMP_INTR when dumping object lists This flag allows to detect that an update has ocurred while dumping any of the object lists. In case of interference, nft cancels the netlink socket to skip processing the remaining stale entries and it retries to obtain fresh list of objects. Signed-off-by: Pablo Neira Ayuso --- src/rule.c | 64 +++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 26 deletions(-) (limited to 'src/rule.c') diff --git a/src/rule.c b/src/rule.c index a7bc6f44..1e545260 100644 --- a/src/rule.c +++ b/src/rule.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -701,12 +702,28 @@ static int do_command_export(struct netlink_ctx *ctx, struct cmd *cmd) return 0; } +static void do_command_list_cleanup(struct table *table) +{ + struct chain *chain, *nchain; + struct set *set, *nset; + + list_for_each_entry_safe(chain, nchain, &table->chains, list) { + list_del(&chain->list); + chain_free(chain); + } + + list_for_each_entry_safe(set, nset, &table->sets, list) { + list_del(&set->list); + set_free(set); + } +} + static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd) { struct table *table = NULL; - struct chain *chain, *nchain; + struct chain *chain; struct rule *rule, *nrule; - struct set *set, *nset; + struct set *set; /* No need to allocate the table object when listing all tables */ if (cmd->handle.table != NULL) { @@ -726,7 +743,7 @@ static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd) if (netlink_list_tables(ctx, &cmd->handle, &cmd->location) < 0) - return -1; + goto err; list_for_each_entry(table, &ctx->list, list) { printf("table %s\n", table->handle.table); @@ -735,39 +752,41 @@ static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd) } /* List content of this table */ if (do_list_sets(ctx, &cmd->location, table) < 0) - return -1; + goto err; if (netlink_list_chains(ctx, &cmd->handle, &cmd->location) < 0) - return -1; + goto err; list_splice_tail_init(&ctx->list, &table->chains); if (netlink_list_table(ctx, &cmd->handle, &cmd->location) < 0) - return -1; + goto err; break; case CMD_OBJ_CHAIN: if (do_list_sets(ctx, &cmd->location, table) < 0) - return -1; + goto err; if (netlink_list_chains(ctx, &cmd->handle, &cmd->location) < 0) - return -1; + goto err; list_splice_tail_init(&ctx->list, &table->chains); if (netlink_list_table(ctx, &cmd->handle, &cmd->location) < 0) - return -1; + goto err; break; case CMD_OBJ_SETS: if (netlink_list_sets(ctx, &cmd->handle, &cmd->location) < 0) - return -1; + goto err; list_for_each_entry(set, &ctx->list, list){ if (netlink_get_setelems(ctx, &set->handle, - &cmd->location, set) < 0) - return -1; + &cmd->location, set) < 0) { + goto err; + } set_print(set); } return 0; case CMD_OBJ_SET: if (netlink_get_set(ctx, &cmd->handle, &cmd->location) < 0) - return -1; + goto err; list_for_each_entry(set, &ctx->list, list) { if (netlink_get_setelems(ctx, &cmd->handle, - &cmd->location, set) < 0) - return -1; + &cmd->location, set) < 0) { + goto err; + } set_print(set); } return 0; @@ -787,18 +806,11 @@ static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd) } table_print(table); - - list_for_each_entry_safe(chain, nchain, &table->chains, list) { - list_del(&chain->list); - chain_free(chain); - } - - list_for_each_entry_safe(set, nset, &table->sets, list) { - list_del(&set->list); - set_free(set); - } - + do_command_list_cleanup(table); return 0; +err: + do_command_list_cleanup(table); + return -1; } static int do_command_flush(struct netlink_ctx *ctx, struct cmd *cmd) -- cgit v1.2.3