diff options
-rw-r--r-- | include/cli.h | 4 | ||||
-rw-r--r-- | include/netlink.h | 4 | ||||
-rw-r--r-- | include/nftables.h | 10 | ||||
-rw-r--r-- | include/parser.h | 4 | ||||
-rw-r--r-- | include/rule.h | 17 | ||||
-rw-r--r-- | src/cli.c | 11 | ||||
-rw-r--r-- | src/evaluate.c | 68 | ||||
-rw-r--r-- | src/main.c | 29 | ||||
-rw-r--r-- | src/netlink.c | 42 | ||||
-rw-r--r-- | src/netlink_delinearize.c | 5 | ||||
-rw-r--r-- | src/parser_bison.y | 5 | ||||
-rw-r--r-- | src/rule.c | 76 |
12 files changed, 155 insertions, 120 deletions
diff --git a/include/cli.h b/include/cli.h index 21052e32..e5774008 100644 --- a/include/cli.h +++ b/include/cli.h @@ -6,10 +6,10 @@ struct parser_state; #ifdef HAVE_LIBREADLINE extern int cli_init(struct nft_ctx *nft, struct mnl_socket *nf_sock, - struct parser_state *state); + struct nft_cache *cache, struct parser_state *state); #else static inline int cli_init(struct nft_ctx *nft, struct mnl_socket *nf_sock, - struct parser_state *state) + struct nft_cache *cache, struct parser_state *state) { return -1; } diff --git a/include/netlink.h b/include/netlink.h index 47ecef38..37261714 100644 --- a/include/netlink.h +++ b/include/netlink.h @@ -39,6 +39,7 @@ extern const struct location netlink_location; * @data: pointer to pass data to callback * @seqnum: sequence number * @octx: output context + * @cache: cache context */ struct netlink_ctx { struct mnl_socket *nf_sock; @@ -50,6 +51,7 @@ struct netlink_ctx { struct nftnl_batch *batch; bool batch_supported; struct output_ctx *octx; + struct nft_cache *cache; }; extern struct nftnl_table *alloc_nftnl_table(const struct handle *h); @@ -162,6 +164,7 @@ extern int netlink_get_set(struct netlink_ctx *ctx, const struct handle *h, const struct location *loc); extern struct stmt *netlink_parse_set_expr(const struct set *set, + const struct nft_cache *cache, const struct nftnl_expr *nle); extern int netlink_add_setelems(struct netlink_ctx *ctx, const struct handle *h, @@ -216,6 +219,7 @@ struct netlink_mon_handler { struct netlink_ctx *ctx; const struct location *loc; bool cache_needed; + struct nft_cache *cache; }; extern int netlink_monitor(struct netlink_mon_handler *monhandler, diff --git a/include/nftables.h b/include/nftables.h index ca609015..a88c86d1 100644 --- a/include/nftables.h +++ b/include/nftables.h @@ -37,6 +37,11 @@ struct nft_ctx { bool check; }; +struct nft_cache { + bool initialized; + struct list_head list; +}; + extern unsigned int max_errors; extern unsigned int debug_level; extern const char *include_paths[INCLUDE_PATHS_MAX]; @@ -117,8 +122,9 @@ struct input_descriptor { struct parser_state; struct mnl_socket; -int nft_run(struct nft_ctx *nft, struct mnl_socket *nf_sock, void *scanner, - struct parser_state *state, struct list_head *msgs); +int nft_run(struct nft_ctx *nft, struct mnl_socket *nf_sock, + struct nft_cache *cache, void *scanner, struct parser_state *state, + struct list_head *msgs); void ct_label_table_init(void); void mark_table_init(void); diff --git a/include/parser.h b/include/parser.h index 1815ea1b..5a452f77 100644 --- a/include/parser.h +++ b/include/parser.h @@ -31,8 +31,8 @@ struct parser_state { struct mnl_socket; -extern void parser_init(struct mnl_socket *nf_sock, struct parser_state *state, - struct list_head *msgs); +extern void parser_init(struct mnl_socket *nf_sock, struct nft_cache *cache, + struct parser_state *state, struct list_head *msgs); extern int nft_parse(void *, struct parser_state *state); extern void *scanner_init(struct parser_state *state); diff --git a/include/rule.h b/include/rule.h index a0edda2f..10ac0e26 100644 --- a/include/rule.h +++ b/include/rule.h @@ -116,8 +116,9 @@ struct table { extern struct table *table_alloc(void); extern struct table *table_get(struct table *table); extern void table_free(struct table *table); -extern void table_add_hash(struct table *table); -extern struct table *table_lookup(const struct handle *h); +extern void table_add_hash(struct table *table, struct nft_cache *cache); +extern struct table *table_lookup(const struct handle *h, + const struct nft_cache *cache); /** * enum chain_flags - chain flags @@ -248,7 +249,7 @@ extern void set_free(struct set *set); extern void set_add_hash(struct set *set, struct table *table); extern struct set *set_lookup(const struct table *table, const char *name); extern struct set *set_lookup_global(uint32_t family, const char *table, - const char *name); + const char *name, struct nft_cache *cache); extern void set_print(const struct set *set, struct output_ctx *octx); extern void set_print_plain(const struct set *s, struct output_ctx *octx); @@ -468,6 +469,7 @@ extern void cmd_free(struct cmd *cmd); * @rule: current rule * @set: current set * @stmt: current statement + * @cache: cache context * @ectx: expression context * @pctx: payload context */ @@ -479,6 +481,7 @@ struct eval_ctx { struct rule *rule; struct set *set; struct stmt *stmt; + struct nft_cache *cache; struct expr_ctx ectx; struct proto_ctx pctx; }; @@ -490,10 +493,10 @@ 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(struct mnl_socket *nf_sock, enum cmd_ops cmd, - struct list_head *msgs); -extern void cache_flush(void); -extern void cache_release(void); +extern int cache_update(struct mnl_socket *nf_sock, struct nft_cache *cache, + enum cmd_ops cmd, struct list_head *msgs); +extern void cache_flush(struct list_head *table_list); +extern void cache_release(struct nft_cache *cache); enum udata_type { UDATA_TYPE_COMMENT, @@ -43,8 +43,8 @@ static const struct input_descriptor indesc_cli = { static struct parser_state *state; static struct nft_ctx cli_nft; static struct mnl_socket *cli_nf_sock; +static struct nft_cache *cli_cache; static void *scanner; - static char histfile[PATH_MAX]; static char *multiline; static bool eof; @@ -135,12 +135,12 @@ static void cli_complete(char *line) xfree(line); line = s; - parser_init(cli_nf_sock, state, &msgs); + parser_init(cli_nf_sock, cli_cache, state, &msgs); scanner_push_buffer(scanner, &indesc_cli, line); - nft_run(&cli_nft, cli_nf_sock, scanner, state, &msgs); + nft_run(&cli_nft, cli_nf_sock, cli_cache, scanner, state, &msgs); erec_print_list(stdout, &msgs); xfree(line); - cache_release(); + cache_release(cli_cache); iface_cache_release(); } @@ -176,12 +176,13 @@ void __fmtstring(1, 0) cli_display(const char *fmt, va_list ap) } int cli_init(struct nft_ctx *nft, struct mnl_socket *nf_sock, - struct parser_state *_state) + struct nft_cache *cache, struct parser_state *_state) { const char *home; cli_nf_sock = nf_sock; cli_nft = *nft; + cli_cache = cache; rl_readline_name = "nft"; rl_instream = stdin; rl_outstream = stdout; diff --git a/src/evaluate.c b/src/evaluate.c index 477fb54d..64e14b8b 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -144,7 +144,7 @@ static struct table *table_lookup_global(struct eval_ctx *ctx) if (ctx->table != NULL) return ctx->table; - table = table_lookup(&ctx->cmd->handle); + table = table_lookup(&ctx->cmd->handle, ctx->cache); if (table == NULL) return NULL; @@ -181,7 +181,8 @@ static int expr_evaluate_symbol(struct eval_ctx *ctx, struct expr **expr) new = expr_clone(sym->expr); break; case SYMBOL_SET: - ret = cache_update(ctx->nf_sock, ctx->cmd->op, ctx->msgs); + ret = cache_update(ctx->nf_sock, ctx->cache, ctx->cmd->op, + ctx->msgs); if (ret < 0) return ret; @@ -2915,13 +2916,13 @@ static int table_evaluate(struct eval_ctx *ctx, struct table *table) struct chain *chain; struct set *set; - if (table_lookup(&ctx->cmd->handle) == NULL) { + if (table_lookup(&ctx->cmd->handle, ctx->cache) == NULL) { if (table == NULL) { table = table_alloc(); handle_merge(&table->handle, &ctx->cmd->handle); - table_add_hash(table); + table_add_hash(table, ctx->cache); } else { - table_add_hash(table_get(table)); + table_add_hash(table_get(table), ctx->cache); } } @@ -2949,26 +2950,30 @@ static int cmd_evaluate_add(struct eval_ctx *ctx, struct cmd *cmd) switch (cmd->obj) { case CMD_OBJ_SETELEM: - ret = cache_update(ctx->nf_sock, cmd->op, ctx->msgs); + ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op, + ctx->msgs); if (ret < 0) return ret; return setelem_evaluate(ctx, &cmd->expr); case CMD_OBJ_SET: - ret = cache_update(ctx->nf_sock, cmd->op, ctx->msgs); + ret = cache_update(ctx->nf_sock, ctx->cache, 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: - ret = cache_update(ctx->nf_sock, cmd->op, ctx->msgs); + ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op, + ctx->msgs); if (ret < 0) return ret; handle_merge(&cmd->rule->handle, &cmd->handle); return rule_evaluate(ctx, cmd->rule); case CMD_OBJ_CHAIN: - ret = cache_update(ctx->nf_sock, cmd->op, ctx->msgs); + ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op, + ctx->msgs); if (ret < 0) return ret; @@ -2978,7 +2983,8 @@ static int cmd_evaluate_add(struct eval_ctx *ctx, struct cmd *cmd) case CMD_OBJ_COUNTER: case CMD_OBJ_QUOTA: case CMD_OBJ_CT_HELPER: - ret = cache_update(ctx->nf_sock, cmd->op, ctx->msgs); + ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op, + ctx->msgs); if (ret < 0) return ret; @@ -2994,7 +3000,8 @@ static int cmd_evaluate_delete(struct eval_ctx *ctx, struct cmd *cmd) switch (cmd->obj) { case CMD_OBJ_SETELEM: - ret = cache_update(ctx->nf_sock, cmd->op, ctx->msgs); + ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op, + ctx->msgs); if (ret < 0) return ret; @@ -3020,7 +3027,7 @@ static int cmd_evaluate_list_obj(struct eval_ctx *ctx, const struct cmd *cmd, if (obj_type == NFT_OBJECT_UNSPEC) obj_type = NFT_OBJECT_COUNTER; - table = table_lookup(&cmd->handle); + table = table_lookup(&cmd->handle, ctx->cache); if (table == NULL) return cmd_error(ctx, "Could not process rule: Table '%s' does not exist", cmd->handle.table); @@ -3036,7 +3043,7 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd) struct set *set; int ret; - ret = cache_update(ctx->nf_sock, cmd->op, ctx->msgs); + ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op, ctx->msgs); if (ret < 0) return ret; @@ -3045,13 +3052,13 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd) if (cmd->handle.table == NULL) return 0; - table = table_lookup(&cmd->handle); + table = table_lookup(&cmd->handle, ctx->cache); if (table == NULL) return cmd_error(ctx, "Could not process rule: Table '%s' does not exist", cmd->handle.table); return 0; case CMD_OBJ_SET: - table = table_lookup(&cmd->handle); + table = table_lookup(&cmd->handle, ctx->cache); if (table == NULL) return cmd_error(ctx, "Could not process rule: Table '%s' does not exist", cmd->handle.table); @@ -3061,7 +3068,7 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd) cmd->handle.set); return 0; case CMD_OBJ_FLOWTABLE: - table = table_lookup(&cmd->handle); + table = table_lookup(&cmd->handle, ctx->cache); if (table == NULL) return cmd_error(ctx, "Could not process rule: Table '%s' does not exist", cmd->handle.table); @@ -3071,7 +3078,7 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd) cmd->handle.set); return 0; case CMD_OBJ_MAP: - table = table_lookup(&cmd->handle); + table = table_lookup(&cmd->handle, ctx->cache); if (table == NULL) return cmd_error(ctx, "Could not process rule: Table '%s' does not exist", cmd->handle.table); @@ -3081,7 +3088,7 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd) cmd->handle.set); return 0; case CMD_OBJ_CHAIN: - table = table_lookup(&cmd->handle); + table = table_lookup(&cmd->handle, ctx->cache); if (table == NULL) return cmd_error(ctx, "Could not process rule: Table '%s' does not exist", cmd->handle.table); @@ -3101,7 +3108,7 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd) case CMD_OBJ_SETS: if (cmd->handle.table == NULL) return 0; - if (table_lookup(&cmd->handle) == NULL) + if (table_lookup(&cmd->handle, ctx->cache) == NULL) return cmd_error(ctx, "Could not process rule: Table '%s' does not exist", cmd->handle.table); return 0; @@ -3119,7 +3126,7 @@ static int cmd_evaluate_reset(struct eval_ctx *ctx, struct cmd *cmd) { int ret; - ret = cache_update(ctx->nf_sock, cmd->op, ctx->msgs); + ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op, ctx->msgs); if (ret < 0) return ret; @@ -3130,7 +3137,7 @@ static int cmd_evaluate_reset(struct eval_ctx *ctx, struct cmd *cmd) case CMD_OBJ_QUOTAS: if (cmd->handle.table == NULL) return 0; - if (table_lookup(&cmd->handle) == NULL) + if (table_lookup(&cmd->handle, ctx->cache) == NULL) return cmd_error(ctx, "Could not process rule: Table '%s' does not exist", cmd->handle.table); return 0; @@ -3145,13 +3152,13 @@ static int cmd_evaluate_flush(struct eval_ctx *ctx, struct cmd *cmd) struct set *set; int ret; - ret = cache_update(ctx->nf_sock, cmd->op, ctx->msgs); + ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op, ctx->msgs); if (ret < 0) return ret; switch (cmd->obj) { case CMD_OBJ_RULESET: - cache_flush(); + cache_flush(&ctx->cache->list); break; case CMD_OBJ_TABLE: /* Flushing a table does not empty the sets in the table nor remove @@ -3161,7 +3168,7 @@ static int cmd_evaluate_flush(struct eval_ctx *ctx, struct cmd *cmd) /* Chains don't hold sets */ break; case CMD_OBJ_SET: - table = table_lookup(&cmd->handle); + table = table_lookup(&cmd->handle, ctx->cache); if (table == NULL) return cmd_error(ctx, "Could not process rule: Table '%s' does not exist", cmd->handle.table); @@ -3171,7 +3178,7 @@ static int cmd_evaluate_flush(struct eval_ctx *ctx, struct cmd *cmd) cmd->handle.set); return 0; case CMD_OBJ_MAP: - table = table_lookup(&cmd->handle); + table = table_lookup(&cmd->handle, ctx->cache); if (table == NULL) return cmd_error(ctx, "Could not process rule: Table '%s' does not exist", cmd->handle.table); @@ -3181,7 +3188,7 @@ static int cmd_evaluate_flush(struct eval_ctx *ctx, struct cmd *cmd) cmd->handle.set); return 0; case CMD_OBJ_FLOWTABLE: - table = table_lookup(&cmd->handle); + table = table_lookup(&cmd->handle, ctx->cache); if (table == NULL) return cmd_error(ctx, "Could not process rule: Table '%s' does not exist", cmd->handle.table); @@ -3203,11 +3210,12 @@ static int cmd_evaluate_rename(struct eval_ctx *ctx, struct cmd *cmd) switch (cmd->obj) { case CMD_OBJ_CHAIN: - ret = cache_update(ctx->nf_sock, cmd->op, ctx->msgs); + ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op, + ctx->msgs); if (ret < 0) return ret; - table = table_lookup(&ctx->cmd->handle); + table = table_lookup(&ctx->cmd->handle, ctx->cache); if (table == NULL) return cmd_error(ctx, "Could not process rule: Table '%s' does not exist", ctx->cmd->handle.table); @@ -3300,7 +3308,7 @@ static int cmd_evaluate_monitor(struct eval_ctx *ctx, struct cmd *cmd) uint32_t event; int ret; - ret = cache_update(ctx->nf_sock, cmd->op, ctx->msgs); + ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op, ctx->msgs); if (ret < 0) return ret; @@ -3321,7 +3329,7 @@ static int cmd_evaluate_monitor(struct eval_ctx *ctx, struct cmd *cmd) static int cmd_evaluate_export(struct eval_ctx *ctx, struct cmd *cmd) { - return cache_update(ctx->nf_sock, cmd->op, ctx->msgs); + return cache_update(ctx->nf_sock, ctx->cache, cmd->op, ctx->msgs); } #ifdef DEBUG @@ -187,8 +187,9 @@ static const struct input_descriptor indesc_cmdline = { .name = "<cmdline>", }; -static int nft_netlink(struct nft_ctx *nft, struct parser_state *state, - struct list_head *msgs, struct mnl_socket *nf_sock) +static int nft_netlink(struct nft_ctx *nft, struct nft_cache *cache, + struct parser_state *state, struct list_head *msgs, + struct mnl_socket *nf_sock) { struct nftnl_batch *batch; struct netlink_ctx ctx; @@ -210,6 +211,7 @@ static int nft_netlink(struct nft_ctx *nft, struct parser_state *state, ctx.batch_supported = batch_supported; ctx.octx = &nft->output; ctx.nf_sock = nf_sock; + ctx.cache = cache; init_list_head(&ctx.list); ret = do_command(&ctx, cmd); if (ret < 0) @@ -244,8 +246,9 @@ out: return ret; } -int nft_run(struct nft_ctx *nft, struct mnl_socket *nf_sock, void *scanner, - struct parser_state *state, struct list_head *msgs) +int nft_run(struct nft_ctx *nft, struct mnl_socket *nf_sock, + struct nft_cache *cache, void *scanner, struct parser_state *state, + struct list_head *msgs) { struct cmd *cmd, *next; int ret; @@ -259,7 +262,7 @@ int nft_run(struct nft_ctx *nft, struct mnl_socket *nf_sock, void *scanner, list_for_each_entry(cmd, &state->cmds, list) nft_cmd_expand(cmd); - ret = nft_netlink(nft, state, msgs, nf_sock); + ret = nft_netlink(nft, cache, state, msgs, nf_sock); err1: list_for_each_entry_safe(cmd, next, &state->cmds, list) { list_del(&cmd->list); @@ -294,6 +297,7 @@ void nft_exit(void) int main(int argc, char * const *argv) { struct parser_state state; + struct nft_cache cache; void *scanner; LIST_HEAD(msgs); char *buf = NULL, *filename = NULL; @@ -302,6 +306,9 @@ int main(int argc, char * const *argv) int i, val, rc = NFT_EXIT_SUCCESS; struct mnl_socket *nf_sock; + memset(&cache, 0, sizeof(cache)); + init_list_head(&cache.list); + nft_init(); nf_sock = netlink_open_sock(); while (1) { @@ -400,20 +407,20 @@ int main(int argc, char * const *argv) strcat(buf, " "); } strcat(buf, "\n"); - parser_init(nf_sock, &state, &msgs); + parser_init(nf_sock, &cache, &state, &msgs); scanner = scanner_init(&state); scanner_push_buffer(scanner, &indesc_cmdline, buf); } else if (filename != NULL) { - rc = cache_update(nf_sock, CMD_INVALID, &msgs); + rc = cache_update(nf_sock, &cache, CMD_INVALID, &msgs); if (rc < 0) return rc; - parser_init(nf_sock, &state, &msgs); + parser_init(nf_sock, &cache, &state, &msgs); scanner = scanner_init(&state); if (scanner_read_file(scanner, filename, &internal_location) < 0) goto out; } else if (interactive) { - if (cli_init(&nft, nf_sock, &state) < 0) { + if (cli_init(&nft, nf_sock, &cache, &state) < 0) { fprintf(stderr, "%s: interactive CLI not supported in this build\n", argv[0]); exit(NFT_EXIT_FAILURE); @@ -424,13 +431,13 @@ int main(int argc, char * const *argv) exit(NFT_EXIT_FAILURE); } - if (nft_run(&nft, nf_sock, scanner, &state, &msgs) != 0) + if (nft_run(&nft, nf_sock, &cache, scanner, &state, &msgs) != 0) rc = NFT_EXIT_FAILURE; out: scanner_destroy(scanner); erec_print_list(stderr, &msgs); xfree(buf); - cache_release(); + cache_release(&cache); iface_cache_release(); netlink_close_sock(nf_sock); nft_exit(); diff --git a/src/netlink.c b/src/netlink.c index b172d2cc..8aef8d9a 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -1623,7 +1623,8 @@ static void set_elem_parse_udata(struct nftnl_set_elem *nlse, } static int netlink_delinearize_setelem(struct nftnl_set_elem *nlse, - const struct set *set) + const struct set *set, + struct nft_cache *cache) { struct nft_data_delinearize nld; struct expr *expr, *key, *data; @@ -1659,7 +1660,7 @@ static int netlink_delinearize_setelem(struct nftnl_set_elem *nlse, const struct nftnl_expr *nle; nle = nftnl_set_elem_get(nlse, NFTNL_SET_ELEM_EXPR, NULL); - expr->stmt = netlink_parse_set_expr(set, nle); + expr->stmt = netlink_parse_set_expr(set, cache, nle); } if (flags & NFT_SET_ELEM_INTERVAL_END) expr->flags |= EXPR_F_INTERVAL_END; @@ -1712,7 +1713,7 @@ int netlink_delete_setelems(struct netlink_ctx *ctx, const struct handle *h, static int list_setelem_cb(struct nftnl_set_elem *nlse, void *arg) { struct netlink_ctx *ctx = arg; - return netlink_delinearize_setelem(nlse, ctx->set); + return netlink_delinearize_setelem(nlse, ctx->set, ctx->cache); } int netlink_get_setelems(struct netlink_ctx *ctx, const struct handle *h, @@ -2037,7 +2038,7 @@ static uint32_t netlink_msg2nftnl_of(uint32_t msg) static void nlr_for_each_set(struct nftnl_rule *nlr, void (*cb)(struct set *s, void *data), - void *data) + void *data, struct nft_cache *cache) { struct nftnl_expr_iter *nlrei; struct nftnl_expr *nlre; @@ -2060,7 +2061,7 @@ static void nlr_for_each_set(struct nftnl_rule *nlr, goto next; set_name = nftnl_expr_get_str(nlre, NFTNL_EXPR_LOOKUP_SET); - s = set_lookup_global(family, table, set_name); + s = set_lookup_global(family, table, set_name, cache); if (s == NULL) goto next; @@ -2269,7 +2270,7 @@ static int netlink_events_setelem_cb(const struct nlmsghdr *nlh, int type, setname = nftnl_set_get_str(nls, NFTNL_SET_NAME); family = nftnl_set_get_u32(nls, NFTNL_SET_FAMILY); - set = set_lookup_global(family, table, setname); + set = set_lookup_global(family, table, setname, monh->cache); if (set == NULL) { fprintf(stderr, "W: Received event for an unknown set."); goto out; @@ -2301,7 +2302,8 @@ static int netlink_events_setelem_cb(const struct nlmsghdr *nlh, int type, nftnl_set_elems_iter_destroy(nlsei); goto out; } - if (netlink_delinearize_setelem(nlse, dummyset) < 0) { + if (netlink_delinearize_setelem(nlse, dummyset, + monh->cache) < 0) { set_free(dummyset); nftnl_set_elems_iter_destroy(nlsei); goto out; @@ -2418,7 +2420,8 @@ static int netlink_events_rule_cb(const struct nlmsghdr *nlh, int type, switch (type) { case NFT_MSG_NEWRULE: r = netlink_delinearize_rule(monh->ctx, nlr); - nlr_for_each_set(nlr, rule_map_decompose_cb, NULL); + nlr_for_each_set(nlr, rule_map_decompose_cb, NULL, + monh->cache); printf("add rule %s %s %s ", family, table, chain); rule_print(r, monh->ctx->octx); @@ -2454,7 +2457,7 @@ static void netlink_events_cache_addtable(struct netlink_mon_handler *monh, t = netlink_delinearize_table(monh->ctx, nlt); nftnl_table_free(nlt); - table_add_hash(t); + table_add_hash(t, monh->cache); } static void netlink_events_cache_deltable(struct netlink_mon_handler *monh, @@ -2468,7 +2471,7 @@ static void netlink_events_cache_deltable(struct netlink_mon_handler *monh, h.family = nftnl_table_get_u32(nlt, NFTNL_TABLE_FAMILY); h.table = nftnl_table_get_str(nlt, NFTNL_TABLE_NAME); - t = table_lookup(&h); + t = table_lookup(&h, monh->cache); if (t == NULL) goto out; @@ -2498,7 +2501,7 @@ static void netlink_events_cache_addset(struct netlink_mon_handler *monh, goto out; s->init = set_expr_alloc(monh->loc, s); - t = table_lookup(&s->handle); + t = table_lookup(&s->handle, monh->cache); if (t == NULL) { fprintf(stderr, "W: Unable to cache set: table not found.\n"); set_free(s); @@ -2525,7 +2528,7 @@ static void netlink_events_cache_addsetelem(struct netlink_mon_handler *monh, table = nftnl_set_get_str(nls, NFTNL_SET_TABLE); setname = nftnl_set_get_str(nls, NFTNL_SET_NAME); - set = set_lookup_global(family, table, setname); + set = set_lookup_global(family, table, setname, monh->cache); if (set == NULL) { fprintf(stderr, "W: Unable to cache set_elem. Set not found.\n"); @@ -2538,7 +2541,7 @@ static void netlink_events_cache_addsetelem(struct netlink_mon_handler *monh, nlse = nftnl_set_elems_iter_next(nlsei); while (nlse != NULL) { - if (netlink_delinearize_setelem(nlse, set) < 0) { + if (netlink_delinearize_setelem(nlse, set, monh->cache) < 0) { fprintf(stderr, "W: Unable to cache set_elem. " "Delinearize failed.\n"); @@ -2564,7 +2567,8 @@ static void netlink_events_cache_delsets(struct netlink_mon_handler *monh, { struct nftnl_rule *nlr = netlink_rule_alloc(nlh); - nlr_for_each_set(nlr, netlink_events_cache_delset_cb, NULL); + nlr_for_each_set(nlr, netlink_events_cache_delset_cb, NULL, + monh->cache); nftnl_rule_free(nlr); } @@ -2587,7 +2591,7 @@ static void netlink_events_cache_addobj(struct netlink_mon_handler *monh, if (obj == NULL) goto out; - t = table_lookup(&obj->handle); + t = table_lookup(&obj->handle, monh->cache); if (t == NULL) { fprintf(stderr, "W: Unable to cache object: table not found.\n"); obj_free(obj); @@ -2616,7 +2620,7 @@ static void netlink_events_cache_delobj(struct netlink_mon_handler *monh, name = nftnl_obj_get_str(nlo, NFTNL_OBJ_NAME); type = nftnl_obj_get_u32(nlo, NFTNL_OBJ_TYPE); - t = table_lookup(&h); + t = table_lookup(&h, monh->cache); if (t == NULL) { fprintf(stderr, "W: Unable to cache object: table not found.\n"); goto out; @@ -2712,7 +2716,7 @@ static void trace_print_verdict(const struct nftnl_trace *nlt, } static void trace_print_rule(const struct nftnl_trace *nlt, - struct output_ctx *octx) + struct output_ctx *octx, struct nft_cache *cache) { const struct table *table; uint64_t rule_handle; @@ -2727,7 +2731,7 @@ static void trace_print_rule(const struct nftnl_trace *nlt, if (!h.table) return; - table = table_lookup(&h); + table = table_lookup(&h, cache); if (!table) return; @@ -2919,7 +2923,7 @@ static int netlink_events_trace_cb(const struct nlmsghdr *nlh, int type, trace_print_packet(nlt, monh->ctx->octx); if (nftnl_trace_is_set(nlt, NFTNL_TRACE_RULE_HANDLE)) - trace_print_rule(nlt, monh->ctx->octx); + trace_print_rule(nlt, monh->ctx->octx, monh->cache); break; case NFT_TRACETYPE_POLICY: case NFT_TRACETYPE_RETURN: diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index 3ee07c0a..5317a830 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -1275,12 +1275,13 @@ static int netlink_parse_rule_expr(struct nftnl_expr *nle, void *arg) } struct stmt *netlink_parse_set_expr(const struct set *set, + const struct nft_cache *cache, const struct nftnl_expr *nle) { struct netlink_parse_ctx ctx, *pctx = &ctx; pctx->rule = rule_alloc(&netlink_location, &set->handle); - pctx->table = table_lookup(&set->handle); + pctx->table = table_lookup(&set->handle, cache); assert(pctx->table != NULL); if (netlink_parse_expr(nle, pctx) < 0) @@ -2306,7 +2307,7 @@ struct rule *netlink_delinearize_rule(struct netlink_ctx *ctx, h.position.id = nftnl_rule_get_u64(nlr, NFTNL_RULE_POSITION); pctx->rule = rule_alloc(&netlink_location, &h); - pctx->table = table_lookup(&h); + pctx->table = table_lookup(&h, ctx->cache); assert(pctx->table != NULL); if (nftnl_rule_is_set(nlr, NFTNL_RULE_USERDATA)) { diff --git a/src/parser_bison.y b/src/parser_bison.y index e7bb9097..783b72f5 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -35,14 +35,15 @@ #include "parser_bison.h" -void parser_init(struct mnl_socket *nf_sock, struct parser_state *state, - struct list_head *msgs) +void parser_init(struct mnl_socket *nf_sock, struct nft_cache *cache, + struct parser_state *state, struct list_head *msgs) { memset(state, 0, sizeof(*state)); init_list_head(&state->cmds); init_list_head(&state->top_scope.symbols); state->msgs = msgs; state->scopes[0] = scope_init(&state->top_scope, NULL); + state->ectx.cache = cache; state->ectx.msgs = msgs; state->ectx.nf_sock = nf_sock; } @@ -53,9 +53,8 @@ void handle_merge(struct handle *dst, const struct handle *src) dst->position = src->position; } -static LIST_HEAD(table_list); - -static int cache_init_tables(struct netlink_ctx *ctx, struct handle *h) +static int cache_init_tables(struct netlink_ctx *ctx, struct handle *h, + struct nft_cache *cache) { int ret; @@ -63,7 +62,7 @@ static int cache_init_tables(struct netlink_ctx *ctx, struct handle *h) if (ret < 0) return -1; - list_splice_tail_init(&ctx->list, &table_list); + list_splice_tail_init(&ctx->list, &cache->list); return 0; } @@ -75,7 +74,7 @@ static int cache_init_objects(struct netlink_ctx *ctx, enum cmd_ops cmd) struct set *set; int ret; - list_for_each_entry(table, &table_list, list) { + list_for_each_entry(table, &ctx->cache->list, list) { ret = netlink_list_sets(ctx, &table->handle, &internal_location); list_splice_tail_init(&ctx->list, &table->sets); @@ -122,8 +121,8 @@ static int cache_init_objects(struct netlink_ctx *ctx, enum cmd_ops cmd) return 0; } -static int cache_init(struct mnl_socket *nf_sock, enum cmd_ops cmd, - struct list_head *msgs) +static int cache_init(struct mnl_socket *nf_sock, struct nft_cache *cache, + enum cmd_ops cmd, struct list_head *msgs) { struct handle handle = { .family = NFPROTO_UNSPEC, @@ -134,9 +133,10 @@ static int cache_init(struct mnl_socket *nf_sock, enum cmd_ops cmd, memset(&ctx, 0, sizeof(ctx)); init_list_head(&ctx.list); ctx.nf_sock = nf_sock; + ctx.cache = cache; ctx.msgs = msgs; - ret = cache_init_tables(&ctx, &handle); + ret = cache_init_tables(&ctx, &handle, cache); if (ret < 0) return ret; ret = cache_init_objects(&ctx, cmd); @@ -146,44 +146,42 @@ static int cache_init(struct mnl_socket *nf_sock, enum cmd_ops cmd, return 0; } -static bool cache_initialized; - -int cache_update(struct mnl_socket *nf_sock, enum cmd_ops cmd, - struct list_head *msgs) +int cache_update(struct mnl_socket *nf_sock, struct nft_cache *cache, + enum cmd_ops cmd, struct list_head *msgs) { int ret; - if (cache_initialized) + if (cache->initialized) return 0; replay: netlink_genid_get(nf_sock); - ret = cache_init(nf_sock, cmd, msgs); + ret = cache_init(nf_sock, cache, cmd, msgs); if (ret < 0) { - cache_release(); + cache_release(cache); if (errno == EINTR) { netlink_restart(nf_sock); goto replay; } return -1; } - cache_initialized = true; + cache->initialized = true; return 0; } -void cache_flush(void) +void cache_flush(struct list_head *table_list) { struct table *table, *next; - list_for_each_entry_safe(table, next, &table_list, list) { + list_for_each_entry_safe(table, next, table_list, list) { list_del(&table->list); table_free(table); } } -void cache_release(void) +void cache_release(struct nft_cache *cache) { - cache_flush(); - cache_initialized = false; + cache_flush(&cache->list); + cache->initialized = false; } /* internal ID to uniquely identify a set in the batch */ @@ -236,7 +234,7 @@ struct set *set_lookup(const struct table *table, const char *name) } struct set *set_lookup_global(uint32_t family, const char *table, - const char *name) + const char *name, struct nft_cache *cache) { struct handle h; struct table *t; @@ -244,7 +242,7 @@ struct set *set_lookup_global(uint32_t family, const char *table, h.family = family; h.table = table; - t = table_lookup(&h); + t = table_lookup(&h, cache); if (t == NULL) return NULL; @@ -745,16 +743,17 @@ struct table *table_get(struct table *table) return table; } -void table_add_hash(struct table *table) +void table_add_hash(struct table *table, struct nft_cache *cache) { - list_add_tail(&table->list, &table_list); + list_add_tail(&table->list, &cache->list); } -struct table *table_lookup(const struct handle *h) +struct table *table_lookup(const struct handle *h, + const struct nft_cache *cache) { struct table *table; - list_for_each_entry(table, &table_list, list) { + list_for_each_entry(table, &cache->list, list) { if (table->handle.family == h->family && !strcmp(table->handle.table, h->table)) return table; @@ -987,7 +986,7 @@ static int do_add_setelems(struct netlink_ctx *ctx, const struct handle *h, struct table *table; struct set *set; - table = table_lookup(h); + table = table_lookup(h, ctx->cache); set = set_lookup(table, h->set); if (set->flags & NFT_SET_INTERVAL && @@ -1077,7 +1076,7 @@ static int do_delete_setelems(struct netlink_ctx *ctx, const struct handle *h, struct table *table; struct set *set; - table = table_lookup(h); + table = table_lookup(h, ctx->cache); set = set_lookup(table, h->set); if (set->flags & NFT_SET_INTERVAL && @@ -1152,7 +1151,7 @@ static int do_list_sets(struct netlink_ctx *ctx, struct cmd *cmd) struct table *table; struct set *set; - list_for_each_entry(table, &table_list, list) { + list_for_each_entry(table, &ctx->cache->list, list) { if (cmd->handle.family != NFPROTO_UNSPEC && cmd->handle.family != table->handle.family) continue; @@ -1355,7 +1354,7 @@ static int do_list_obj(struct netlink_ctx *ctx, struct cmd *cmd, uint32_t type) struct table *table; struct obj *obj; - list_for_each_entry(table, &table_list, list) { + list_for_each_entry(table, &ctx->cache->list, list) { if (cmd->handle.family != NFPROTO_UNSPEC && cmd->handle.family != table->handle.family) continue; @@ -1389,7 +1388,7 @@ static int do_list_ruleset(struct netlink_ctx *ctx, struct cmd *cmd) unsigned int family = cmd->handle.family; struct table *table; - list_for_each_entry(table, &table_list, list) { + list_for_each_entry(table, &ctx->cache->list, list) { if (family != NFPROTO_UNSPEC && table->handle.family != family) continue; @@ -1410,7 +1409,7 @@ static int do_list_tables(struct netlink_ctx *ctx, struct cmd *cmd) { struct table *table; - list_for_each_entry(table, &table_list, list) { + list_for_each_entry(table, &ctx->cache->list, list) { if (cmd->handle.family != NFPROTO_UNSPEC && cmd->handle.family != table->handle.family) continue; @@ -1455,7 +1454,7 @@ static int do_list_chains(struct netlink_ctx *ctx, struct cmd *cmd) struct table *table; struct chain *chain; - list_for_each_entry(table, &table_list, list) { + list_for_each_entry(table, &ctx->cache->list, list) { if (cmd->handle.family != NFPROTO_UNSPEC && cmd->handle.family != table->handle.family) continue; @@ -1493,7 +1492,7 @@ static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd) struct table *table = NULL; if (cmd->handle.table != NULL) - table = table_lookup(&cmd->handle); + table = table_lookup(&cmd->handle, ctx->cache); switch (cmd->obj) { case CMD_OBJ_TABLE: @@ -1559,7 +1558,7 @@ static int do_command_reset(struct netlink_ctx *ctx, struct cmd *cmd) ret = netlink_reset_objs(ctx, &cmd->handle, &cmd->location, type, dump); list_for_each_entry_safe(obj, next, &ctx->list, list) { - table = table_lookup(&obj->handle); + table = table_lookup(&obj->handle, ctx->cache); list_move(&obj->list, &table->objs); } if (ret < 0) @@ -1590,7 +1589,7 @@ static int do_command_flush(struct netlink_ctx *ctx, struct cmd *cmd) static int do_command_rename(struct netlink_ctx *ctx, struct cmd *cmd) { - struct table *table = table_lookup(&cmd->handle); + struct table *table = table_lookup(&cmd->handle, ctx->cache); struct chain *chain; switch (cmd->obj) { @@ -1634,7 +1633,7 @@ static int do_command_monitor(struct netlink_ctx *ctx, struct cmd *cmd) struct chain *chain; int ret; - list_for_each_entry(t, &table_list, list) { + list_for_each_entry(t, &ctx->cache->list, list) { list_for_each_entry(s, &t->sets, list) s->init = set_expr_alloc(&cmd->location, s); @@ -1665,6 +1664,7 @@ static int do_command_monitor(struct netlink_ctx *ctx, struct cmd *cmd) monhandler.format = cmd->monitor->format; monhandler.ctx = ctx; monhandler.loc = &cmd->location; + monhandler.cache = ctx->cache; return netlink_monitor(&monhandler, ctx->nf_sock); } |