diff options
-rw-r--r-- | include/netlink.h | 2 | ||||
-rw-r--r-- | src/main.c | 8 | ||||
-rw-r--r-- | src/netlink.c | 42 | ||||
-rw-r--r-- | src/rule.c | 64 |
4 files changed, 83 insertions, 33 deletions
diff --git a/include/netlink.h b/include/netlink.h index 4ef7365f..af5dcd94 100644 --- a/include/netlink.h +++ b/include/netlink.h @@ -137,6 +137,8 @@ extern void netlink_dump_expr(struct nft_rule_expr *nle); extern void netlink_dump_set(struct nft_set *nls); extern int netlink_batch_send(struct list_head *err_list); + +extern void netlink_restart(void); extern void netlink_abi_error(void) __noreturn; extern int netlink_io_error(struct netlink_ctx *ctx, const struct location *loc, const char *fmt, ...); @@ -223,8 +223,14 @@ int nft_run(void *scanner, struct parser_state *state, struct list_head *msgs) ret = nft_parse(scanner, state); if (ret != 0 || state->nerrs > 0) return -1; +retry: + ret = nft_netlink(state, msgs); + if (ret < 0 && errno == EINTR) { + netlink_restart(); + goto retry; + } - return nft_netlink(state, msgs); + return ret; } int main(int argc, char * const *argv) diff --git a/src/netlink.c b/src/netlink.c index 987dd63e..afad5a46 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -70,6 +70,12 @@ static void __exit netlink_close_sock(void) mnl_socket_close(nf_mon_sock); } +void netlink_restart(void) +{ + netlink_close_sock(); + netlink_open_sock(); +} + static void netlink_open_mon_sock(void) { nf_mon_sock = nfsock_open(); @@ -443,10 +449,14 @@ static int netlink_list_rules(struct netlink_ctx *ctx, const struct handle *h, struct nft_rule_list *rule_cache; rule_cache = mnl_nft_rule_dump(nf_sock, h->family); - if (rule_cache == NULL) + if (rule_cache == NULL) { + if (errno == EINTR) + return -1; + return netlink_io_error(ctx, loc, "Could not receive rules from kernel: %s", strerror(errno)); + } ctx->data = h; nft_rule_list_foreach(rule_cache, list_rule_cb, ctx); @@ -704,10 +714,14 @@ int netlink_list_chains(struct netlink_ctx *ctx, const struct handle *h, struct chain *chain; chain_cache = mnl_nft_chain_dump(nf_sock, h->family); - if (chain_cache == NULL) + if (chain_cache == NULL) { + if (errno == EINTR) + return -1; + return netlink_io_error(ctx, loc, "Could not receive chains from kernel: %s", strerror(errno)); + } ctx->data = h; nft_chain_list_foreach(chain_cache, list_chain_cb, ctx); @@ -907,10 +921,14 @@ int netlink_list_tables(struct netlink_ctx *ctx, const struct handle *h, struct nft_table_list *table_cache; table_cache = mnl_nft_table_dump(nf_sock, h->family); - if (table_cache == NULL) + if (table_cache == NULL) { + if (errno == EINTR) + return -1; + return netlink_io_error(ctx, loc, "Could not receive tables from kernel: %s", strerror(errno)); + } nft_table_list_foreach(table_cache, list_table_cb, ctx); nft_table_list_free(table_cache); @@ -1177,10 +1195,14 @@ int netlink_list_sets(struct netlink_ctx *ctx, const struct handle *h, int err; set_cache = mnl_nft_set_dump(nf_sock, h->family, h->table); - if (set_cache == NULL) + if (set_cache == NULL) { + if (errno == EINTR) + return -1; + return netlink_io_error(ctx, loc, "Could not receive sets from kernel: %s", strerror(errno)); + } err = nft_set_list_foreach(set_cache, list_set_cb, ctx); nft_set_list_free(set_cache); @@ -1393,8 +1415,12 @@ int netlink_get_setelems(struct netlink_ctx *ctx, const struct handle *h, netlink_dump_set(nls); err = mnl_nft_setelem_get(nf_sock, nls); - if (err < 0) + if (err < 0) { + if (errno == EINTR) + return -1; + goto out; + } ctx->set = set; set->init = set_expr_alloc(loc); @@ -1423,9 +1449,13 @@ struct nft_ruleset *netlink_dump_ruleset(struct netlink_ctx *ctx, struct nft_ruleset *rs; rs = mnl_nft_ruleset_dump(nf_sock, h->family); - if (rs == NULL) + if (rs == NULL) { + if (errno == EINTR) + return NULL; + netlink_io_error(ctx, loc, "Could not receive ruleset: %s", strerror(errno)); + } return rs; } @@ -14,6 +14,7 @@ #include <stdint.h> #include <string.h> #include <inttypes.h> +#include <errno.h> #include <statement.h> #include <rule.h> @@ -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) |