extern int netlink_add_chain(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc,
- const struct chain *chain);
+ const struct chain *chain, bool excl);
extern int netlink_rename_chain(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc, const char *name);
extern int netlink_delete_chain(struct netlink_ctx *ctx, const struct handle *h,
extern int netlink_add_table(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc,
- const struct table *table);
+ const struct table *table, bool excl);
extern int netlink_delete_table(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc);
extern int netlink_list_tables(struct netlink_ctx *ctx, const struct handle *h,
* enum cmd_ops - command operations
*
* @CMD_INVALID: invalid
- * @CMD_ADD: add object
+ * @CMD_ADD: add object (non-exclusive)
+ * @CMD_CREATE: create object (exclusive)
* @CMD_INSERT: insert object
* @CMD_DELETE: delete object
* @CMD_LIST: list container
enum cmd_ops {
CMD_INVALID,
CMD_ADD,
+ CMD_CREATE,
CMD_INSERT,
CMD_DELETE,
CMD_LIST,
ctx->cmd = cmd;
switch (cmd->op) {
case CMD_ADD:
+ case CMD_CREATE:
case CMD_INSERT:
return cmd_evaluate_add(ctx, cmd);
case CMD_DELETE:
nlh = nft_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
NFT_MSG_NEWRULE,
nft_rule_attr_get_u32(nlr, NFT_RULE_ATTR_FAMILY),
- flags|NLM_F_CREATE, seqnum);
+ NLM_F_CREATE | flags, seqnum);
nft_rule_nlmsg_build_payload(nlh, nlr);
if (!mnl_nlmsg_batch_next(batch))
nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE,
nft_rule_attr_get_u32(nlr, NFT_RULE_ATTR_FAMILY),
- flags|NLM_F_ACK|NLM_F_CREATE, seq);
+ NLM_F_ACK | NLM_F_CREATE | flags, seq);
nft_rule_nlmsg_build_payload(nlh, nlr);
return mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);
nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN,
nft_chain_attr_get_u32(nlc, NFT_CHAIN_ATTR_FAMILY),
- NLM_F_CREATE|NLM_F_ACK|flags, seq);
+ NLM_F_CREATE | NLM_F_ACK | flags, seq);
nft_chain_nlmsg_build_payload(nlh, nlc);
return mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);
nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN,
nft_chain_attr_get_u32(nlc, NFT_CHAIN_ATTR_FAMILY),
- NLM_F_ACK|flags, seq);
+ NLM_F_ACK | flags, seq);
nft_chain_nlmsg_build_payload(nlh, nlc);
return mnl_talk(nf_sock, nlh, nlh->nlmsg_len, chain_get_cb, nlc);
nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE,
nft_table_attr_get_u32(nlt, NFT_TABLE_ATTR_FAMILY),
- NLM_F_EXCL|NLM_F_ACK, seq);
+ NLM_F_ACK | flags, seq);
nft_table_nlmsg_build_payload(nlh, nlt);
return mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);
nlh = nft_set_nlmsg_build_hdr(buf, NFT_MSG_NEWSET,
nft_set_attr_get_u32(nls, NFT_SET_ATTR_FAMILY),
- flags|NLM_F_CREATE|NLM_F_ACK, seq);
+ NLM_F_CREATE | NLM_F_ACK | flags, seq);
nft_set_nlmsg_build_payload(nlh, nls);
return mnl_talk(nf_sock, nlh, nlh->nlmsg_len, set_add_cb, nls);
nlh = nft_set_elem_nlmsg_build_hdr(buf, NFT_MSG_NEWSETELEM,
nft_set_attr_get_u32(nls, NFT_SET_ATTR_FAMILY),
- NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK, seq);
+ NLM_F_CREATE | NLM_F_ACK | flags, seq);
nft_set_elems_nlmsg_build_payload(nlh, nls);
return mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);
}
int netlink_add_chain(struct netlink_ctx *ctx, const struct handle *h,
- const struct location *loc, const struct chain *chain)
+ const struct location *loc, const struct chain *chain,
+ bool excl)
{
struct nft_chain *nlc;
int err;
chain->type);
}
netlink_dump_chain(nlc);
- err = mnl_nft_chain_add(nf_sock, nlc, NLM_F_EXCL);
+ err = mnl_nft_chain_add(nf_sock, nlc, excl ? NLM_F_EXCL : 0);
nft_chain_free(nlc);
if (err < 0)
}
int netlink_add_table(struct netlink_ctx *ctx, const struct handle *h,
- const struct location *loc, const struct table *table)
+ const struct location *loc, const struct table *table,
+ bool excl)
{
struct nft_table *nlt;
int err;
nlt = alloc_nft_table(h);
- err = mnl_nft_table_add(nf_sock, nlt, NLM_F_EXCL);
+ err = mnl_nft_table_add(nf_sock, nlt, excl ? NLM_F_EXCL : 0);
nft_table_free(nlt);
if (err < 0)
%token INET "inet"
%token ADD "add"
+%token CREATE "create"
%token INSERT "insert"
%token DELETE "delete"
%token LIST "list"
%type <cmd> line
%destructor { cmd_free($$); } line
-%type <cmd> base_cmd add_cmd insert_cmd delete_cmd list_cmd flush_cmd rename_cmd
-%destructor { cmd_free($$); } base_cmd add_cmd insert_cmd delete_cmd list_cmd flush_cmd rename_cmd
+%type <cmd> base_cmd add_cmd create_cmd insert_cmd delete_cmd list_cmd flush_cmd rename_cmd
+%destructor { cmd_free($$); } base_cmd add_cmd create_cmd insert_cmd delete_cmd list_cmd flush_cmd rename_cmd
%type <handle> table_spec tables_spec chain_spec chain_identifier ruleid_spec
%destructor { handle_free(&$$); } table_spec tables_spec chain_spec chain_identifier ruleid_spec
base_cmd : /* empty */ add_cmd { $$ = $1; }
| ADD add_cmd { $$ = $2; }
+ | CREATE create_cmd { $$ = $2; }
| INSERT insert_cmd { $$ = $2; }
| DELETE delete_cmd { $$ = $2; }
| LIST list_cmd { $$ = $2; }
}
;
+create_cmd : TABLE table_spec
+ {
+ $$ = cmd_alloc(CMD_CREATE, CMD_OBJ_TABLE, &$2, &@$, NULL);
+ }
+ | TABLE table_spec table_block_alloc
+ '{' table_block '}'
+ {
+ handle_merge(&$3->handle, &$2);
+ close_scope(state);
+ $$ = cmd_alloc(CMD_CREATE, CMD_OBJ_TABLE, &$2, &@$, $5);
+ }
+ | CHAIN chain_spec
+ {
+ $$ = cmd_alloc(CMD_CREATE, CMD_OBJ_CHAIN, &$2, &@$, NULL);
+ }
+ | CHAIN chain_spec chain_block_alloc
+ '{' chain_block '}'
+ {
+ $5->location = @5;
+ handle_merge(&$3->handle, &$2);
+ close_scope(state);
+ $$ = cmd_alloc(CMD_CREATE, CMD_OBJ_CHAIN, &$2, &@$, $5);
+ }
+ ;
+
insert_cmd : RULE ruleid_spec rule
{
$$ = cmd_alloc(CMD_INSERT, CMD_OBJ_RULE, &$2, &@$, $3);
#include <netlink.h>
static int do_add_chain(struct netlink_ctx *ctx, const struct handle *h,
- const struct location *loc, struct chain *chain)
+ const struct location *loc, struct chain *chain,
+ bool excl)
{
- if (netlink_add_chain(ctx, h, loc, chain) < 0)
+ if (netlink_add_chain(ctx, h, loc, chain, excl) < 0)
return -1;
if (chain != NULL) {
if (netlink_add_rule_list(ctx, h, &chain->rules) < 0)
}
static int do_add_table(struct netlink_ctx *ctx, const struct handle *h,
- const struct location *loc, struct table *table)
+ const struct location *loc, struct table *table,
+ bool excl)
{
struct chain *chain;
struct set *set;
- if (netlink_add_table(ctx, h, loc, table) < 0)
+ if (netlink_add_table(ctx, h, loc, table, excl) < 0)
return -1;
if (table != NULL) {
list_for_each_entry(set, &table->sets, list) {
}
list_for_each_entry(chain, &table->chains, list) {
if (do_add_chain(ctx, &chain->handle, &chain->location,
- chain) < 0)
+ chain, excl) < 0)
return -1;
}
}
return 0;
}
-static int do_command_add(struct netlink_ctx *ctx, struct cmd *cmd)
+static int do_command_add(struct netlink_ctx *ctx, struct cmd *cmd, bool excl)
{
switch (cmd->obj) {
case CMD_OBJ_TABLE:
return do_add_table(ctx, &cmd->handle, &cmd->location,
- cmd->table);
+ cmd->table, excl);
case CMD_OBJ_CHAIN:
return do_add_chain(ctx, &cmd->handle, &cmd->location,
- cmd->chain);
+ cmd->chain, excl);
case CMD_OBJ_RULE:
return netlink_add_rule_batch(ctx, &cmd->handle,
cmd->rule, NLM_F_APPEND);
{
switch (cmd->op) {
case CMD_ADD:
- return do_command_add(ctx, cmd);
+ return do_command_add(ctx, cmd, false);
+ case CMD_CREATE:
+ return do_command_add(ctx, cmd, true);
case CMD_INSERT:
return do_command_insert(ctx, cmd);
case CMD_DELETE:
"inet" { return INET; }
"add" { return ADD; }
+"create" { return CREATE; }
"insert" { return INSERT; }
"delete" { return DELETE; }
"list" { return LIST; }