summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/mnl.h2
-rw-r--r--include/netlink.h4
-rw-r--r--include/rule.h2
-rw-r--r--src/evaluate.c1
-rw-r--r--src/mnl.c16
-rw-r--r--src/netlink.c18
-rw-r--r--src/parser_bison.y12
-rw-r--r--src/rule.c14
-rw-r--r--src/scanner.l1
9 files changed, 68 insertions, 2 deletions
diff --git a/include/mnl.h b/include/mnl.h
index 9c14e1aa..f74dfee5 100644
--- a/include/mnl.h
+++ b/include/mnl.h
@@ -26,6 +26,8 @@ int mnl_nft_rule_batch_add(struct nftnl_rule *nlr, unsigned int flags,
uint32_t seqnum);
int mnl_nft_rule_batch_del(struct nftnl_rule *nlr, unsigned int flags,
uint32_t seqnum);
+int mnl_nft_rule_batch_replace(struct nftnl_rule *nlr, unsigned int flags,
+ uint32_t seqnum);
int mnl_nft_rule_add(struct mnl_socket *nf_sock, struct nftnl_rule *r,
unsigned int flags);
diff --git a/include/netlink.h b/include/netlink.h
index 7bf7ea0d..84447422 100644
--- a/include/netlink.h
+++ b/include/netlink.h
@@ -98,6 +98,10 @@ extern int netlink_add_rule_batch(struct netlink_ctx *ctx,
extern int netlink_del_rule_batch(struct netlink_ctx *ctx,
const struct handle *h,
const struct location *loc);
+extern int netlink_replace_rule_batch(struct netlink_ctx *ctx,
+ const struct handle *h,
+ const struct rule *rule,
+ const struct location *loc);
extern int netlink_add_chain(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc,
diff --git a/include/rule.h b/include/rule.h
index 30b4597d..a86f600b 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -237,6 +237,7 @@ extern void set_print_plain(const struct set *s);
*
* @CMD_INVALID: invalid
* @CMD_ADD: add object (non-exclusive)
+ * @CMD_REPLACE, replace object
* @CMD_CREATE: create object (exclusive)
* @CMD_INSERT: insert object
* @CMD_DELETE: delete object
@@ -250,6 +251,7 @@ extern void set_print_plain(const struct set *s);
enum cmd_ops {
CMD_INVALID,
CMD_ADD,
+ CMD_REPLACE,
CMD_CREATE,
CMD_INSERT,
CMD_DELETE,
diff --git a/src/evaluate.c b/src/evaluate.c
index ea43fc1b..e776d2cf 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -2241,6 +2241,7 @@ int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd)
ctx->cmd = cmd;
switch (cmd->op) {
case CMD_ADD:
+ case CMD_REPLACE:
case CMD_CREATE:
case CMD_INSERT:
return cmd_evaluate_add(ctx, cmd);
diff --git a/src/mnl.c b/src/mnl.c
index e4253e53..52875f4a 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -301,6 +301,22 @@ int mnl_nft_rule_batch_add(struct nftnl_rule *nlr, unsigned int flags,
return 0;
}
+int mnl_nft_rule_batch_replace(struct nftnl_rule *nlr, unsigned int flags,
+ uint32_t seqnum)
+{
+ struct nlmsghdr *nlh;
+
+ nlh = nftnl_rule_nlmsg_build_hdr(nftnl_batch_buffer(batch),
+ NFT_MSG_NEWRULE,
+ nftnl_rule_get_u32(nlr, NFTNL_RULE_FAMILY),
+ NLM_F_REPLACE | flags, seqnum);
+
+ nftnl_rule_nlmsg_build_payload(nlh, nlr);
+ mnl_nft_batch_continue();
+
+ return 0;
+}
+
int mnl_nft_rule_batch_del(struct nftnl_rule *nlr, unsigned int flags,
uint32_t seqnum)
{
diff --git a/src/netlink.c b/src/netlink.c
index 4d1e977f..ad86084e 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -382,6 +382,24 @@ int netlink_add_rule_batch(struct netlink_ctx *ctx,
return err;
}
+int netlink_replace_rule_batch(struct netlink_ctx *ctx, const struct handle *h,
+ const struct rule *rule,
+ const struct location *loc)
+{
+ struct nftnl_rule *nlr;
+ int err;
+
+ nlr = alloc_nftnl_rule(&rule->handle);
+ netlink_linearize_rule(ctx, nlr, rule);
+ err = mnl_nft_rule_batch_replace(nlr, 0, ctx->seqnum);
+ nftnl_rule_free(nlr);
+
+ if (err < 0)
+ netlink_io_error(ctx, loc, "Could not replace rule to batch: %s",
+ strerror(errno));
+ return err;
+}
+
int netlink_add_rule_list(struct netlink_ctx *ctx, const struct handle *h,
struct list_head *rule_list)
{
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 98480b60..519eabbf 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -184,6 +184,7 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%token ADD "add"
%token UPDATE "update"
+%token REPLACE "replace"
%token CREATE "create"
%token INSERT "insert"
%token DELETE "delete"
@@ -413,8 +414,8 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%type <cmd> line
%destructor { cmd_free($$); } line
-%type <cmd> base_cmd add_cmd create_cmd insert_cmd delete_cmd list_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd
-%destructor { cmd_free($$); } base_cmd add_cmd create_cmd insert_cmd delete_cmd list_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd
+%type <cmd> base_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd list_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd
+%destructor { cmd_free($$); } base_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd list_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd
%type <handle> table_spec chain_spec chain_identifier ruleid_spec ruleset_spec
%destructor { handle_free(&$$); } table_spec chain_spec chain_identifier ruleid_spec ruleset_spec
@@ -649,6 +650,7 @@ line : common_block { $$ = NULL; }
base_cmd : /* empty */ add_cmd { $$ = $1; }
| ADD add_cmd { $$ = $2; }
+ | REPLACE replace_cmd { $$ = $2; }
| CREATE create_cmd { $$ = $2; }
| INSERT insert_cmd { $$ = $2; }
| DELETE delete_cmd { $$ = $2; }
@@ -711,6 +713,12 @@ add_cmd : TABLE table_spec
}
;
+replace_cmd : RULE ruleid_spec rule
+ {
+ $$ = cmd_alloc(CMD_REPLACE, CMD_OBJ_RULE, &$2, &@$, $3);
+ }
+ ;
+
create_cmd : TABLE table_spec
{
$$ = cmd_alloc(CMD_CREATE, CMD_OBJ_TABLE, &$2, &@$, NULL);
diff --git a/src/rule.c b/src/rule.c
index 0a814693..c154062b 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -935,6 +935,18 @@ static int do_command_add(struct netlink_ctx *ctx, struct cmd *cmd, bool excl)
return 0;
}
+static int do_command_replace(struct netlink_ctx *ctx, struct cmd *cmd)
+{
+ switch (cmd->obj) {
+ case CMD_OBJ_RULE:
+ return netlink_replace_rule_batch(ctx, &cmd->handle, cmd->rule,
+ &cmd->location);
+ default:
+ BUG("invalid command object type %u\n", cmd->obj);
+ }
+ return 0;
+}
+
static int do_command_insert(struct netlink_ctx *ctx, struct cmd *cmd)
{
switch (cmd->obj) {
@@ -1229,6 +1241,8 @@ int do_command(struct netlink_ctx *ctx, struct cmd *cmd)
return do_command_add(ctx, cmd, true);
case CMD_INSERT:
return do_command_insert(ctx, cmd);
+ case CMD_REPLACE:
+ return do_command_replace(ctx, cmd);
case CMD_DELETE:
return do_command_delete(ctx, cmd);
case CMD_LIST:
diff --git a/src/scanner.l b/src/scanner.l
index b827489a..1a9f43f8 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -259,6 +259,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"netdev" { return NETDEV; }
"add" { return ADD; }
+"replace" { return REPLACE; }
"update" { return UPDATE; }
"create" { return CREATE; }
"insert" { return INSERT; }