struct parser_state;
#ifdef HAVE_LIBREADLINE
-extern int cli_init(struct nft_ctx *nft, struct parser_state *state);
+extern int cli_init(struct nft_ctx *nft, struct mnl_socket *nf_sock,
+ struct parser_state *state);
#else
-static inline int cli_init(struct nft_ctx *nft, struct parser_state *state)
+static inline int cli_init(struct nft_ctx *nft, struct mnl_socket *nf_sock,
+ struct parser_state *state)
{
return -1;
}
struct mnl_socket;
+struct mnl_socket *netlink_open_sock(void);
+void netlink_close_sock(struct mnl_socket *nf_sock);
+
uint32_t mnl_seqnum_alloc(void);
void mnl_genid_get(struct mnl_socket *nf_sock);
* @octx: output context
*/
struct netlink_ctx {
+ struct mnl_socket *nf_sock;
struct list_head *msgs;
struct list_head list;
struct set *set;
extern int netlink_batch_send(struct netlink_ctx *ctx, struct list_head *err_list);
-extern void netlink_genid_get(void);
-extern void netlink_restart(void);
+extern void netlink_genid_get(struct mnl_socket *nf_sock);
+extern void netlink_restart(struct mnl_socket *nf_sock);
#define netlink_abi_error() \
__netlink_abi_error(__FILE__, __LINE__, strerror(errno));
extern void __noreturn __netlink_abi_error(const char *file, int line, const char *reason);
};
extern int netlink_monitor(struct netlink_mon_handler *monhandler);
-bool netlink_batch_supported(void);
+bool netlink_batch_supported(struct mnl_socket *nf_sock);
#endif /* NFTABLES_NETLINK_H */
};
struct parser_state;
+struct mnl_socket;
-int nft_run(struct nft_ctx *nft, void *scanner, struct parser_state *state,
- struct list_head *msgs);
+int nft_run(struct nft_ctx *nft, struct mnl_socket *nf_sock, void *scanner,
+ struct parser_state *state, struct list_head *msgs);
#endif /* NFTABLES_NFTABLES_H */
struct eval_ctx ectx;
};
-extern void parser_init(struct parser_state *state, struct list_head *msgs);
+struct mnl_socket;
+
+extern void parser_init(struct mnl_socket *nf_sock, 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);
/**
* struct eval_ctx - evaluation context
*
+ * @nf_sock: netlink socket (for caching)
* @msgs: message queue
* @cmd: current command
* @table: current table
* @pctx: payload context
*/
struct eval_ctx {
+ struct mnl_socket *nf_sock;
struct list_head *msgs;
struct cmd *cmd;
struct table *table;
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 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);
#include <iface.h>
#include <cli.h>
+#include <libmnl/libmnl.h>
+
#define CMDLINE_HISTFILE ".nft.history"
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 void *scanner;
static char histfile[PATH_MAX];
xfree(line);
line = s;
- parser_init(state, &msgs);
+ parser_init(cli_nf_sock, state, &msgs);
scanner_push_buffer(scanner, &indesc_cli, line);
- nft_run(&cli_nft, scanner, state, &msgs);
+ nft_run(&cli_nft, cli_nf_sock, scanner, state, &msgs);
erec_print_list(stdout, &msgs);
xfree(line);
cache_release();
rl_forced_update_display();
}
-int cli_init(struct nft_ctx *nft, struct parser_state *_state)
+int cli_init(struct nft_ctx *nft, struct mnl_socket *nf_sock,
+ struct parser_state *_state)
{
const char *home;
+ cli_nf_sock = nf_sock;
cli_nft = *nft;
rl_readline_name = "nft";
rl_instream = stdin;
new = expr_clone(sym->expr);
break;
case SYMBOL_SET:
- ret = cache_update(ctx->cmd->op, ctx->msgs);
+ ret = cache_update(ctx->nf_sock, ctx->cmd->op, ctx->msgs);
if (ret < 0)
return ret;
switch (cmd->obj) {
case CMD_OBJ_SETELEM:
- ret = cache_update(cmd->op, ctx->msgs);
+ ret = cache_update(ctx->nf_sock, cmd->op, ctx->msgs);
if (ret < 0)
return ret;
return setelem_evaluate(ctx, &cmd->expr);
case CMD_OBJ_SET:
- ret = cache_update(cmd->op, ctx->msgs);
+ ret = cache_update(ctx->nf_sock, 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(cmd->op, ctx->msgs);
+ ret = cache_update(ctx->nf_sock, cmd->op, ctx->msgs);
if (ret < 0)
return ret;
switch (cmd->obj) {
case CMD_OBJ_SETELEM:
- ret = cache_update(cmd->op, ctx->msgs);
+ ret = cache_update(ctx->nf_sock, cmd->op, ctx->msgs);
if (ret < 0)
return ret;
struct set *set;
int ret;
- ret = cache_update(cmd->op, ctx->msgs);
+ ret = cache_update(ctx->nf_sock, cmd->op, ctx->msgs);
if (ret < 0)
return ret;
{
int ret;
- ret = cache_update(cmd->op, ctx->msgs);
+ ret = cache_update(ctx->nf_sock, cmd->op, ctx->msgs);
if (ret < 0)
return ret;
struct set *set;
int ret;
- ret = cache_update(cmd->op, ctx->msgs);
+ ret = cache_update(ctx->nf_sock, cmd->op, ctx->msgs);
if (ret < 0)
return ret;
switch (cmd->obj) {
case CMD_OBJ_CHAIN:
- ret = cache_update(cmd->op, ctx->msgs);
+ ret = cache_update(ctx->nf_sock, cmd->op, ctx->msgs);
if (ret < 0)
return ret;
uint32_t event;
int ret;
- ret = cache_update(cmd->op, ctx->msgs);
+ ret = cache_update(ctx->nf_sock, cmd->op, ctx->msgs);
if (ret < 0)
return ret;
static int cmd_evaluate_export(struct eval_ctx *ctx, struct cmd *cmd)
{
- return cache_update(cmd->op, ctx->msgs);
+ return cache_update(ctx->nf_sock, cmd->op, ctx->msgs);
}
#ifdef DEBUG
};
static int nft_netlink(struct nft_ctx *nft, struct parser_state *state,
- struct list_head *msgs)
+ struct list_head *msgs, struct mnl_socket *nf_sock)
{
struct nftnl_batch *batch;
struct netlink_ctx ctx;
struct mnl_err *err, *tmp;
LIST_HEAD(err_list);
uint32_t batch_seqnum;
- bool batch_supported = netlink_batch_supported();
+ bool batch_supported = netlink_batch_supported(nf_sock);
int ret = 0;
batch = mnl_batch_init();
ctx.batch = batch;
ctx.batch_supported = batch_supported;
ctx.octx = &nft->output;
+ ctx.nf_sock = nf_sock;
init_list_head(&ctx.list);
ret = do_command(&ctx, cmd);
if (ret < 0)
return ret;
}
-int nft_run(struct nft_ctx *nft, void *scanner, struct parser_state *state,
- struct list_head *msgs)
+int nft_run(struct nft_ctx *nft, struct mnl_socket *nf_sock, void *scanner,
+ struct parser_state *state, struct list_head *msgs)
{
struct cmd *cmd, *next;
int ret;
list_for_each_entry(cmd, &state->cmds, list)
nft_cmd_expand(cmd);
- ret = nft_netlink(nft, state, msgs);
+ ret = nft_netlink(nft, state, msgs, nf_sock);
err1:
list_for_each_entry_safe(cmd, next, &state->cmds, list) {
list_del(&cmd->list);
unsigned int len;
bool interactive = false;
int i, val, rc = NFT_EXIT_SUCCESS;
+ struct mnl_socket *nf_sock;
+ nf_sock = netlink_open_sock();
while (1) {
val = getopt_long(argc, argv, OPTSTRING, options, NULL);
if (val == -1)
strcat(buf, " ");
}
strcat(buf, "\n");
- parser_init(&state, &msgs);
+ parser_init(nf_sock, &state, &msgs);
scanner = scanner_init(&state);
scanner_push_buffer(scanner, &indesc_cmdline, buf);
} else if (filename != NULL) {
- rc = cache_update(CMD_INVALID, &msgs);
+ rc = cache_update(nf_sock, CMD_INVALID, &msgs);
if (rc < 0)
return rc;
- parser_init(&state, &msgs);
+ parser_init(nf_sock, &state, &msgs);
scanner = scanner_init(&state);
if (scanner_read_file(scanner, filename, &internal_location) < 0)
goto out;
} else if (interactive) {
- if (cli_init(&nft, &state) < 0) {
+ if (cli_init(&nft, nf_sock, &state) < 0) {
fprintf(stderr, "%s: interactive CLI not supported in this build\n",
argv[0]);
exit(NFT_EXIT_FAILURE);
exit(NFT_EXIT_FAILURE);
}
- if (nft_run(&nft, scanner, &state, &msgs) != 0)
+ if (nft_run(&nft, nf_sock, scanner, &state, &msgs) != 0)
rc = NFT_EXIT_FAILURE;
out:
scanner_destroy(scanner);
xfree(buf);
cache_release();
iface_cache_release();
+ netlink_close_sock(nf_sock);
return rc;
}
#include <erec.h>
#include <iface.h>
-static struct mnl_socket *nf_sock;
static struct mnl_socket *nf_mon_sock;
const struct input_descriptor indesc_netlink = {
return s;
}
-static void __init netlink_open_sock(void)
+struct mnl_socket *netlink_open_sock(void)
{
+ struct mnl_socket *nf_sock;
+
nf_sock = nfsock_open();
fcntl(mnl_socket_get_fd(nf_sock), F_SETFL, O_NONBLOCK);
+ return nf_sock;
}
-static void __exit netlink_close_sock(void)
+void netlink_close_sock(struct mnl_socket *nf_sock)
{
if (nf_sock)
mnl_socket_close(nf_sock);
mnl_socket_close(nf_mon_sock);
}
-void netlink_restart(void)
+void netlink_restart(struct mnl_socket *nf_sock)
{
- netlink_close_sock();
- netlink_open_sock();
+ netlink_close_sock(nf_sock);
+ nf_sock = netlink_open_sock();
}
-void netlink_genid_get(void)
+void netlink_genid_get(struct mnl_socket *nf_sock)
{
mnl_genid_get(nf_sock);
}
{
struct nftnl_rule_list *rule_cache;
- rule_cache = mnl_nft_rule_dump(nf_sock, h->family);
+ rule_cache = mnl_nft_rule_dump(ctx->nf_sock, h->family);
if (rule_cache == NULL) {
if (errno == EINTR)
return -1;
}
netlink_dump_chain(nlc);
- err = mnl_nft_chain_add(nf_sock, nlc, excl ? NLM_F_EXCL : 0);
+ err = mnl_nft_chain_add(ctx->nf_sock, nlc, excl ? NLM_F_EXCL : 0);
nftnl_chain_free(nlc);
if (err < 0)
nlc = alloc_nftnl_chain(h);
nftnl_chain_set_str(nlc, NFTNL_CHAIN_NAME, name);
netlink_dump_chain(nlc);
- err = mnl_nft_chain_add(nf_sock, nlc, 0);
+ err = mnl_nft_chain_add(ctx->nf_sock, nlc, 0);
nftnl_chain_free(nlc);
if (err < 0)
nlc = alloc_nftnl_chain(h);
netlink_dump_chain(nlc);
- err = mnl_nft_chain_delete(nf_sock, nlc, 0);
+ err = mnl_nft_chain_delete(ctx->nf_sock, nlc, 0);
nftnl_chain_free(nlc);
if (err < 0)
struct nftnl_chain_list *chain_cache;
struct chain *chain;
- chain_cache = mnl_nft_chain_dump(nf_sock, h->family);
+ chain_cache = mnl_nft_chain_dump(ctx->nf_sock, h->family);
if (chain_cache == NULL) {
if (errno == EINTR)
return -1;
int err;
nlc = alloc_nftnl_chain(h);
- err = mnl_nft_chain_get(nf_sock, nlc, 0);
+ err = mnl_nft_chain_get(ctx->nf_sock, nlc, 0);
if (err < 0) {
netlink_io_error(ctx, loc,
"Could not receive chain from kernel: %s",
int err;
nlt = alloc_nftnl_table(h);
- err = mnl_nft_table_add(nf_sock, nlt, excl ? NLM_F_EXCL : 0);
+ err = mnl_nft_table_add(ctx->nf_sock, nlt, excl ? NLM_F_EXCL : 0);
nftnl_table_free(nlt);
if (err < 0)
int err;
nlt = alloc_nftnl_table(h);
- err = mnl_nft_table_delete(nf_sock, nlt, 0);
+ err = mnl_nft_table_delete(ctx->nf_sock, nlt, 0);
nftnl_table_free(nlt);
if (err < 0)
{
struct nftnl_table_list *table_cache;
- table_cache = mnl_nft_table_dump(nf_sock, h->family);
+ table_cache = mnl_nft_table_dump(ctx->nf_sock, h->family);
if (table_cache == NULL) {
if (errno == EINTR)
return -1;
int err;
nlt = alloc_nftnl_table(h);
- err = mnl_nft_table_get(nf_sock, nlt, 0);
+ err = mnl_nft_table_get(ctx->nf_sock, nlt, 0);
if (err < 0) {
netlink_io_error(ctx, loc,
"Could not receive table from kernel: %s",
}
netlink_dump_set(nls);
- err = mnl_nft_set_add(nf_sock, nls, NLM_F_ECHO | flags);
+ err = mnl_nft_set_add(ctx->nf_sock, nls, NLM_F_ECHO | flags);
if (err < 0)
netlink_io_error(ctx, &set->location, "Could not add set: %s",
strerror(errno));
int err;
nls = alloc_nftnl_set(h);
- err = mnl_nft_set_delete(nf_sock, nls, 0);
+ err = mnl_nft_set_delete(ctx->nf_sock, nls, 0);
nftnl_set_free(nls);
if (err < 0)
struct nftnl_set_list *set_cache;
int err;
- set_cache = mnl_nft_set_dump(nf_sock, h->family, h->table);
+ set_cache = mnl_nft_set_dump(ctx->nf_sock, h->family, h->table);
if (set_cache == NULL) {
if (errno == EINTR)
return -1;
int err;
nls = alloc_nftnl_set(h);
- err = mnl_nft_set_get(nf_sock, nls);
+ err = mnl_nft_set_get(ctx->nf_sock, nls);
if (err < 0) {
nftnl_set_free(nls);
return netlink_io_error(ctx, loc,
alloc_setelem_cache(expr, nls);
netlink_dump_set(nls);
- err = mnl_nft_setelem_add(nf_sock, nls, excl ? NLM_F_EXCL : 0);
+ err = mnl_nft_setelem_add(ctx->nf_sock, nls, excl ? NLM_F_EXCL : 0);
nftnl_set_free(nls);
if (err < 0)
netlink_io_error(ctx, &expr->location,
alloc_setelem_cache(expr, nls);
netlink_dump_set(nls);
- err = mnl_nft_setelem_delete(nf_sock, nls, 0);
+ err = mnl_nft_setelem_delete(ctx->nf_sock, nls, 0);
nftnl_set_free(nls);
if (err < 0)
netlink_io_error(ctx, &expr->location,
nls = alloc_nftnl_set(h);
- err = mnl_nft_setelem_get(nf_sock, nls);
+ err = mnl_nft_setelem_get(ctx->nf_sock, nls);
if (err < 0) {
nftnl_set_free(nls);
if (errno == EINTR)
struct nftnl_obj_list *obj_cache;
int err;
- obj_cache = mnl_nft_obj_dump(nf_sock, h->family, h->table, NULL,
+ obj_cache = mnl_nft_obj_dump(ctx->nf_sock, h->family, h->table, NULL,
0, true, false);
if (obj_cache == NULL) {
if (errno == EINTR)
struct nftnl_obj_list *obj_cache;
int err;
- obj_cache = mnl_nft_obj_dump(nf_sock, h->family, h->table, h->obj,
+ obj_cache = mnl_nft_obj_dump(ctx->nf_sock, h->family, h->table, h->obj,
type, dump, true);
if (obj_cache == NULL) {
if (errno == EINTR)
int netlink_batch_send(struct netlink_ctx *ctx, struct list_head *err_list)
{
- return mnl_batch_talk(nf_sock, ctx->batch, err_list);
+ return mnl_batch_talk(ctx->nf_sock, ctx->batch, err_list);
}
int netlink_flush_ruleset(struct netlink_ctx *ctx, const struct handle *h,
{
struct nftnl_ruleset *rs;
- rs = mnl_nft_ruleset_dump(nf_sock, h->family);
+ rs = mnl_nft_ruleset_dump(ctx->nf_sock, h->family);
if (rs == NULL) {
if (errno == EINTR)
return NULL;
monhandler);
}
-bool netlink_batch_supported(void)
+bool netlink_batch_supported(struct mnl_socket *nf_sock)
{
return mnl_batch_supported(nf_sock);
}
#include "parser_bison.h"
-void parser_init(struct parser_state *state, struct list_head *msgs)
+void parser_init(struct mnl_socket *nf_sock, struct parser_state *state,
+ struct list_head *msgs)
{
memset(state, 0, sizeof(*state));
init_list_head(&state->cmds);
state->msgs = msgs;
state->scopes[0] = scope_init(&state->top_scope, NULL);
state->ectx.msgs = msgs;
+ state->ectx.nf_sock = nf_sock;
}
static void yyerror(struct location *loc, void *scanner,
return 0;
}
-static int cache_init(enum cmd_ops cmd, struct list_head *msgs)
+static int cache_init(struct mnl_socket *nf_sock, enum cmd_ops cmd,
+ struct list_head *msgs)
{
struct handle handle = {
.family = NFPROTO_UNSPEC,
memset(&ctx, 0, sizeof(ctx));
init_list_head(&ctx.list);
+ ctx.nf_sock = nf_sock;
ctx.msgs = msgs;
ret = cache_init_tables(&ctx, &handle);
static bool cache_initialized;
-int cache_update(enum cmd_ops cmd, struct list_head *msgs)
+int cache_update(struct mnl_socket *nf_sock, enum cmd_ops cmd,
+ struct list_head *msgs)
{
int ret;
if (cache_initialized)
return 0;
replay:
- netlink_genid_get();
- ret = cache_init(cmd, msgs);
+ netlink_genid_get(nf_sock);
+ ret = cache_init(nf_sock, cmd, msgs);
if (ret < 0) {
cache_release();
if (errno == EINTR) {
- netlink_restart();
+ netlink_restart(nf_sock);
goto replay;
}
return -1;