From: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
To: netfilter-devel@vger.kernel.org
Cc: kaber@trash.net, pablo@netfilter.org
Subject: [nft RFC PATCH] src: add import operation
Date: Tue, 21 Jan 2014 18:02:11 +0100 [thread overview]
Message-ID: <20140121170211.31038.31659.stgit@nfdev.cica.es> (raw)
The import operation reads XML/JSON data from stdin.
A basic way to test is:
% nft export json | nft import json
This operation flush the kernel ruleset before adding the one imported.
Adding data from a file:
% cat file.json | nft import json
% nft import json < file.json
Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
---
include/mnl.h | 23 ++++
include/netlink.h | 12 ++
include/rule.h | 2
src/evaluate.c | 1
src/mnl.c | 278 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/netlink.c | 195 +++++++++++++++++++++++++++++++++++++
src/parser.y | 21 +++-
src/rule.c | 50 ++++++++++
src/scanner.l | 1
9 files changed, 579 insertions(+), 4 deletions(-)
diff --git a/include/mnl.h b/include/mnl.h
index f4de27d..bbb5b6f 100644
--- a/include/mnl.h
+++ b/include/mnl.h
@@ -23,6 +23,7 @@ void mnl_batch_end(void);
int mnl_batch_talk(struct mnl_socket *nl, struct list_head *err_list);
int mnl_nft_rule_batch_add(struct nft_rule *nlr, unsigned int flags,
uint32_t seqnum);
+int mnl_nft_rule_list_add(struct nft_rule_list *nlrl, unsigned int flags);
int mnl_nft_rule_batch_del(struct nft_rule *nlr, unsigned int flags,
uint32_t seqnum);
@@ -35,8 +36,13 @@ struct nft_rule_list *mnl_nft_rule_dump(struct mnl_socket *nf_sock,
int mnl_nft_chain_add(struct mnl_socket *nf_sock, struct nft_chain *nlc,
unsigned int flags);
+int mnl_nft_chain_list_add(struct mnl_socket *nf_sock,
+ struct nft_chain_list *nlcl,
+ unsigned int flags);
int mnl_nft_chain_delete(struct mnl_socket *nf_sock, struct nft_chain *nlc,
unsigned int flags);
+int mnl_nft_chain_list_delete(struct mnl_socket *nfsock,
+ struct nft_chain_list *nlcl, unsigned int flags);
struct nft_chain_list *mnl_nft_chain_dump(struct mnl_socket *nf_sock,
int family);
int mnl_nft_chain_get(struct mnl_socket *nf_sock, struct nft_chain *nlc,
@@ -44,8 +50,13 @@ int mnl_nft_chain_get(struct mnl_socket *nf_sock, struct nft_chain *nlc,
int mnl_nft_table_add(struct mnl_socket *nf_sock, struct nft_table *nlt,
unsigned int flags);
+int mnl_nft_table_list_add(struct mnl_socket *nf_sock,
+ struct nft_table_list *nltl,
+ unsigned int flags);
int mnl_nft_table_delete(struct mnl_socket *nf_sock, struct nft_table *nlt,
unsigned int flags);
+int mnl_nft_table_list_delete(struct mnl_socket *nfsock,
+ struct nft_table_list *nltl, unsigned int flags);
struct nft_table_list *mnl_nft_table_dump(struct mnl_socket *nf_sock,
int family);
int mnl_nft_table_get(struct mnl_socket *nf_sock, struct nft_table *nlt,
@@ -53,18 +64,30 @@ int mnl_nft_table_get(struct mnl_socket *nf_sock, struct nft_table *nlt,
int mnl_nft_set_add(struct mnl_socket *nf_sock, struct nft_set *nls,
unsigned int flags);
+int mnl_nft_set_list_add(struct mnl_socket *nf_sock,
+ struct nft_set_list *nlsl,
+ unsigned int flags);
int mnl_nft_set_delete(struct mnl_socket *nf_sock, struct nft_set *nls,
unsigned int flags);
+int mnl_nft_set_list_delete(struct mnl_socket *nfsock,
+ struct nft_set_list *nlsl, unsigned int flags);
struct nft_set_list *mnl_nft_set_dump(struct mnl_socket *nf_sock, int family,
const char *table);
int mnl_nft_set_get(struct mnl_socket *nf_sock, struct nft_set *nls);
int mnl_nft_setelem_add(struct mnl_socket *nf_sock, struct nft_set *nls,
unsigned int flags);
+int mnl_nft_set_elem_list_add(struct mnl_socket *nf_sock,
+ struct nft_set_list *nlsl,
+ unsigned int flags);
int mnl_nft_setelem_delete(struct mnl_socket *nf_sock, struct nft_set *nls,
unsigned int flags);
int mnl_nft_setelem_get(struct mnl_socket *nf_sock, struct nft_set *nls);
struct nft_ruleset *mnl_nft_ruleset_dump(struct mnl_socket *nf_sock,
uint32_t family);
+int mnl_nft_ruleset_add(struct mnl_socket *nf_sock, struct nft_ruleset *rs,
+ unsigned int tflags, unsigned int cflags,
+ unsigned int rflags, unsigned int sflags,
+ unsigned int seflags);
#endif /* _NFTABLES_MNL_H_ */
diff --git a/include/netlink.h b/include/netlink.h
index cfd8462..92982d7 100644
--- a/include/netlink.h
+++ b/include/netlink.h
@@ -139,4 +139,16 @@ extern int netlink_io_error(struct netlink_ctx *ctx,
extern struct nft_ruleset *netlink_dump_ruleset(struct netlink_ctx *ctx,
const struct handle *h,
const struct location *loc);
+extern int netlink_flush_ruleset(struct netlink_ctx *ctx,
+ const struct handle *h,
+ const struct location *loc);
+extern int netlink_delete_ruleset(struct netlink_ctx *ctx,
+ const struct handle *h,
+ const struct location *loc);
+extern int netlink_wipe_ruleset(struct netlink_ctx *ctx,
+ const struct handle *h,
+ const struct location *loc);
+extern int netlink_add_ruleset(struct netlink_ctx *ctx,
+ const struct location *loc,
+ struct nft_ruleset *rs);
#endif /* NFTABLES_NETLINK_H */
diff --git a/include/rule.h b/include/rule.h
index 886aadc..0905ff1 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -205,6 +205,7 @@ extern void set_print(const struct set *set);
* @CMD_FLUSH: flush container
* @CMD_RENAME: rename object
* @CMD_EXPORT: export the ruleset in a given format
+ * @CMD_IMPORT: import a ruleset in a given format
*/
enum cmd_ops {
CMD_INVALID,
@@ -215,6 +216,7 @@ enum cmd_ops {
CMD_FLUSH,
CMD_RENAME,
CMD_EXPORT,
+ CMD_IMPORT,
};
/**
diff --git a/src/evaluate.c b/src/evaluate.c
index 2c26d03..279c752 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1392,6 +1392,7 @@ static int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd)
case CMD_FLUSH:
case CMD_RENAME:
case CMD_EXPORT:
+ case CMD_IMPORT:
return 0;
default:
BUG("invalid command operation %u\n", cmd->op);
diff --git a/src/mnl.c b/src/mnl.c
index 30e9cc6..6a0b977 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -291,6 +291,29 @@ int mnl_nft_rule_batch_add(struct nft_rule *nlr, unsigned int flags,
return 0;
}
+int mnl_nft_rule_list_add(struct nft_rule_list *nlrl, unsigned int flags)
+{
+ int ret = 0;
+ struct nft_rule_list_iter *i;
+ struct nft_rule *r;
+
+ i = nft_rule_list_iter_create(nlrl);
+ if (i == NULL)
+ memory_allocation_error();
+
+ r = nft_rule_list_iter_next(i);
+ while (r != NULL) {
+ ret = mnl_nft_rule_batch_add(r, flags, mnl_seqnum_alloc());
+ if (ret != 0)
+ return ret;
+
+ r = nft_rule_list_iter_next(i);
+ }
+ nft_rule_list_iter_destroy(i);
+
+ return ret;
+}
+
int mnl_nft_rule_batch_del(struct nft_rule *nlr, unsigned int flags,
uint32_t seqnum)
{
@@ -402,6 +425,32 @@ int mnl_nft_chain_add(struct mnl_socket *nf_sock, struct nft_chain *nlc,
return mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);
}
+int mnl_nft_chain_list_add(struct mnl_socket *nf_sock,
+ struct nft_chain_list *nlcl,
+ unsigned int flags)
+{
+ int ret = 0;
+ struct nft_chain_list_iter *i;
+ struct nft_chain *c;
+
+ i = nft_chain_list_iter_create(nlcl);
+ if (i == NULL)
+ memory_allocation_error();
+
+ c = nft_chain_list_iter_next(i);
+ while (c != NULL) {
+ ret = mnl_nft_chain_add(nf_sock, c, flags);
+
+ if (ret != 0)
+ break;
+
+ c = nft_chain_list_iter_next(i);
+ }
+ nft_chain_list_iter_destroy(i);
+
+ return ret;
+}
+
int mnl_nft_chain_delete(struct mnl_socket *nf_sock, struct nft_chain *nlc,
unsigned int flags)
{
@@ -416,6 +465,31 @@ int mnl_nft_chain_delete(struct mnl_socket *nf_sock, struct nft_chain *nlc,
return mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);
}
+int mnl_nft_chain_list_delete(struct mnl_socket *nfsock,
+ struct nft_chain_list *nlcl, unsigned int flags)
+{
+ struct nft_chain_list_iter *i;
+ struct nft_chain *c;
+ int ret = 0;
+
+ i = nft_chain_list_iter_create(nlcl);
+ if (i == NULL)
+ memory_allocation_error();
+
+ c = nft_chain_list_iter_next(i);
+ while (c != NULL) {
+ ret = mnl_nft_chain_delete(nfsock, c, flags);
+
+ if (ret < 0)
+ break;
+
+ c = nft_chain_list_iter_next(i);
+ }
+ nft_chain_list_iter_destroy(i);
+
+ return ret;
+}
+
static int chain_cb(const struct nlmsghdr *nlh, void *data)
{
struct nft_chain_list *nlc_list = data;
@@ -497,6 +571,32 @@ int mnl_nft_table_add(struct mnl_socket *nf_sock, struct nft_table *nlt,
return mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);
}
+int mnl_nft_table_list_add(struct mnl_socket *nf_sock,
+ struct nft_table_list *nltl,
+ unsigned int flags)
+{
+ int ret = 0;
+ struct nft_table_list_iter *i;
+ struct nft_table *t;
+
+ i = nft_table_list_iter_create(nltl);
+ if (i == NULL)
+ memory_allocation_error();
+
+ t = nft_table_list_iter_next(i);
+ while (t != NULL) {
+ ret = mnl_nft_table_add(nf_sock, t, flags);
+
+ if (ret != 0)
+ break;
+
+ t = nft_table_list_iter_next(i);
+ }
+ nft_table_list_iter_destroy(i);
+
+ return ret;
+}
+
int mnl_nft_table_delete(struct mnl_socket *nf_sock, struct nft_table *nlt,
unsigned int flags)
{
@@ -511,6 +611,31 @@ int mnl_nft_table_delete(struct mnl_socket *nf_sock, struct nft_table *nlt,
return mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);
}
+int mnl_nft_table_list_delete(struct mnl_socket *nfsock,
+ struct nft_table_list *nltl, unsigned int flags)
+{
+ struct nft_table_list_iter *i;
+ struct nft_table *t;
+ int ret = 0;
+
+ i = nft_table_list_iter_create(nltl);
+ if (i == NULL)
+ memory_allocation_error();
+
+ t = nft_table_list_iter_next(i);
+ while (t != NULL) {
+ ret = mnl_nft_table_delete(nfsock, t, flags);
+
+ if (ret < 0)
+ break;
+
+ t = nft_table_list_iter_next(i);
+ }
+ nft_table_list_iter_destroy(i);
+
+ return ret;
+}
+
static int table_cb(const struct nlmsghdr *nlh, void *data)
{
struct nft_table_list *nlt_list = data;
@@ -598,6 +723,32 @@ int mnl_nft_set_add(struct mnl_socket *nf_sock, struct nft_set *nls,
return mnl_talk(nf_sock, nlh, nlh->nlmsg_len, set_add_cb, nls);
}
+int mnl_nft_set_list_add(struct mnl_socket *nf_sock,
+ struct nft_set_list *nlsl,
+ unsigned int flags)
+{
+ int ret = 0;
+ struct nft_set_list_iter *i;
+ struct nft_set *s;
+
+ i = nft_set_list_iter_create(nlsl);
+ if (i == NULL)
+ memory_allocation_error();
+
+ s = nft_set_list_iter_next(i);
+ while (s != NULL) {
+ ret = mnl_nft_set_add(nf_sock, s, flags);
+
+ if (ret != 0)
+ break;
+
+ s = nft_set_list_iter_next(i);
+ }
+ nft_set_list_iter_destroy(i);
+
+ return ret;
+}
+
int mnl_nft_set_delete(struct mnl_socket *nf_sock, struct nft_set *nls,
unsigned int flags)
{
@@ -612,6 +763,31 @@ int mnl_nft_set_delete(struct mnl_socket *nf_sock, struct nft_set *nls,
return mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);
}
+int mnl_nft_set_list_delete(struct mnl_socket *nfsock,
+ struct nft_set_list *nlsl, unsigned int flags)
+{
+ struct nft_set_list_iter *i;
+ struct nft_set *s;
+ int ret = 0;
+
+ i = nft_set_list_iter_create(nlsl);
+ if (i == NULL)
+ memory_allocation_error();
+
+ s = nft_set_list_iter_next(i);
+ while (s != NULL) {
+ ret = mnl_nft_set_delete(nfsock, s, flags);
+
+ if (ret < 0)
+ break;
+
+ s = nft_set_list_iter_next(i);
+ }
+ nft_set_list_iter_destroy(i);
+
+ return ret;
+}
+
static int set_cb(const struct nlmsghdr *nlh, void *data)
{
struct nft_set_list *nls_list = data;
@@ -704,6 +880,32 @@ int mnl_nft_setelem_add(struct mnl_socket *nf_sock, struct nft_set *nls,
return mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);
}
+int mnl_nft_set_elem_list_add(struct mnl_socket *nf_sock,
+ struct nft_set_list *nlsl,
+ unsigned int flags)
+{
+ int ret = 0;
+ struct nft_set_list_iter *i;
+ struct nft_set *s;
+
+ i = nft_set_list_iter_create(nlsl);
+ if (i == NULL)
+ memory_allocation_error();
+
+ s = nft_set_list_iter_next(i);
+ while (s != NULL) {
+ ret = mnl_nft_setelem_add(nf_sock, s, flags);
+
+ if (ret != 0)
+ break;
+
+ s = nft_set_list_iter_next(i);
+ }
+ nft_set_list_iter_destroy(i);
+
+ return ret;
+}
+
int mnl_nft_setelem_delete(struct mnl_socket *nf_sock, struct nft_set *nls,
unsigned int flags)
{
@@ -795,3 +997,79 @@ out:
nft_ruleset_free(rs);
return NULL;
}
+
+int mnl_nft_ruleset_add(struct mnl_socket *nf_sock, struct nft_ruleset *rs,
+ unsigned int tflags, unsigned int cflags,
+ unsigned int rflags, unsigned int sflags,
+ unsigned int seflags)
+{
+ int ret = 0;
+ struct nft_table_list *t;
+ struct nft_chain_list *c;
+ struct nft_set_list *s;
+ struct nft_rule_list *r;
+
+#ifdef DEBUG
+ if (debug_level & DEBUG_NETLINK)
+ fprintf(stdout, "mnl_nft_ruleset_add()\n");
+#endif
+
+ if (nft_ruleset_attr_is_set(rs, NFT_RULESET_ATTR_TABLELIST)) {
+ t = (struct nft_table_list *)
+ nft_ruleset_attr_get(rs, NFT_RULESET_ATTR_TABLELIST);
+ ret = mnl_nft_table_list_add(nf_sock, t, tflags);
+ if (ret != 0)
+ return ret;
+#ifdef DEBUG
+ if (debug_level & DEBUG_NETLINK)
+ fprintf(stdout, "mnl_nft_ruleset_add() tables OK\n");
+#endif
+ }
+
+ if (nft_ruleset_attr_is_set(rs, NFT_RULESET_ATTR_CHAINLIST)) {
+ c = (struct nft_chain_list *)
+ nft_ruleset_attr_get(rs, NFT_RULESET_ATTR_CHAINLIST);
+ ret = mnl_nft_chain_list_add(nf_sock, c, cflags);
+ if (ret != 0)
+ return ret;
+#ifdef DEBUG
+ if (debug_level & DEBUG_NETLINK)
+ fprintf(stdout, "mnl_nft_ruleset_add() chains OK\n");
+#endif
+ }
+
+ if (nft_ruleset_attr_is_set(rs, NFT_RULESET_ATTR_SETLIST)) {
+ s = (struct nft_set_list *)
+ nft_ruleset_attr_get(rs, NFT_RULESET_ATTR_SETLIST);
+ ret = mnl_nft_set_list_add(nf_sock, s, sflags);
+ if (ret != 0)
+ return ret;
+#ifdef DEBUG
+ if (debug_level & DEBUG_NETLINK)
+ fprintf(stdout, "mnl_nft_ruleset_add() sets OK\n");
+#endif
+
+ ret = mnl_nft_set_elem_list_add(nf_sock, s, seflags);
+ if (ret != 0)
+ return ret;
+
+#ifdef DEBUG
+ if (debug_level & DEBUG_NETLINK)
+ fprintf(stdout, "mnl_nft_ruleset_add() set_elems OK\n");
+#endif
+ }
+
+ if (nft_ruleset_attr_is_set(rs, NFT_RULESET_ATTR_RULELIST)) {
+ r = (struct nft_rule_list *)
+ nft_ruleset_attr_get(rs, NFT_RULESET_ATTR_RULELIST);
+ ret = mnl_nft_rule_list_add(r, rflags);
+ if (ret != 0)
+ return ret;
+#ifdef DEBUG
+ if (debug_level & DEBUG_NETLINK)
+ fprintf(stdout, "mnl_nft_ruleset_add() rules OK\n");
+#endif
+ }
+
+ return ret;
+}
diff --git a/src/netlink.c b/src/netlink.c
index e3bfc37..d9306ce 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -16,6 +16,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <libnftnl/ruleset.h>
#include <libnftnl/table.h>
#include <libnftnl/chain.h>
#include <libnftnl/expr.h>
@@ -1065,3 +1066,197 @@ struct nft_ruleset *netlink_dump_ruleset(struct netlink_ctx *ctx,
return rs;
}
+
+int netlink_flush_ruleset(struct netlink_ctx *ctx, const struct handle *h,
+ const struct location *loc)
+{
+ struct table *table;
+
+ if (netlink_list_tables(ctx, h, loc) < 0)
+ return -1;
+
+ list_for_each_entry(table, &ctx->list, list) {
+ if (netlink_flush_table(ctx, &table->handle, loc) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+static void filter_sets(struct nft_set_list *sl, uint32_t flags)
+{
+ struct nft_set_list_iter *i;
+ struct nft_set *s;
+
+ i = nft_set_list_iter_create(sl);
+ if (i == NULL)
+ memory_allocation_error();
+
+ s = nft_set_list_iter_next(i);
+ while (s != NULL) {
+ if (nft_set_attr_get_u32(s, NFT_SET_ATTR_FLAGS) & flags) {
+ nft_set_list_del(s);
+ nft_set_free(s);
+ }
+ s = nft_set_list_iter_next(i);
+ }
+ nft_set_list_iter_destroy(i);
+}
+
+int netlink_delete_ruleset(struct netlink_ctx *ctx, const struct handle *h,
+ const struct location *loc)
+{
+ struct nft_chain_list *chain_cache;
+ struct nft_set_list *set_cache;
+ struct nft_table_list *table_cache;
+
+ chain_cache = mnl_nft_chain_dump(nf_sock, h->family);
+ if (chain_cache == NULL)
+ return netlink_io_error(ctx, loc,
+ "Could not receive chains from kernel:"
+ " %s", strerror(errno));
+
+ if (mnl_nft_chain_list_delete(nf_sock, chain_cache, 0) < 0) {
+ nft_chain_list_free(chain_cache);
+ return netlink_io_error(ctx, loc,
+ "Could not delete chain:"
+ " %s", strerror(errno));
+ }
+
+ nft_chain_list_free(chain_cache);
+
+ set_cache = mnl_nft_set_dump(nf_sock, h->family, NULL);
+ if (set_cache == NULL)
+ return netlink_io_error(ctx, loc,
+ "Could not receive sets from kernel:"
+ " %s", strerror(errno));
+
+ /*sleep(1);*/
+
+ /* don't delete ANONYMOUS sets: kernel does it */
+ filter_sets(set_cache, NFT_SET_ANONYMOUS);
+
+ if (mnl_nft_set_list_delete(nf_sock, set_cache, 0) < 0) {
+ nft_set_list_free(set_cache);
+ return netlink_io_error(ctx, loc,
+ "Could not delete set:"
+ " %s", strerror(errno));
+ }
+ nft_set_list_free(set_cache);
+
+ table_cache = mnl_nft_table_dump(nf_sock, h->family);
+ if (table_cache == NULL)
+ return netlink_io_error(ctx, loc,
+ "Could not receive tables from kernel:"
+ " %s", strerror(errno));
+ if (mnl_nft_table_list_delete(nf_sock, table_cache, 0) < 0) {
+ nft_table_list_free(table_cache);
+ return netlink_io_error(ctx, loc,
+ "Could not delete table:"
+ " %s", strerror(errno));
+ }
+ nft_table_list_free(table_cache);
+
+ return 0;
+}
+
+int netlink_wipe_ruleset(struct netlink_ctx *ctx, const struct handle *h,
+ const struct location *loc)
+{
+ LIST_HEAD(err_list);
+
+ /* Batch is expected to start at src/main.c:nft_netlink() */
+
+ if (netlink_flush_ruleset(ctx, h, loc) < 0)
+ return -1;
+
+ /* commit the transaction now, otherwise
+ * netlink_delete_ruleset() cannot be handled.
+ */
+ mnl_batch_end();
+ if (netlink_batch_send(&err_list) < 0)
+ return -1;
+
+ mnl_batch_reset();
+
+ if (netlink_delete_ruleset(ctx, h, loc) < 0)
+ return -1;
+
+ return 0;
+}
+
+static void ruleset_setup(struct nft_ruleset *rs)
+{
+ struct nft_chain *c;
+ struct nft_chain_list *cl;
+ struct nft_chain_list_iter *ci;
+ struct nft_rule_list *rl;
+ struct nft_rule *r;
+ struct nft_rule_list_iter *ri;
+ struct nft_rule_list *reverse_rule_list;
+
+ if (nft_ruleset_attr_is_set(rs, NFT_RULESET_ATTR_CHAINLIST)) {
+ cl = (struct nft_chain_list *)
+ nft_ruleset_attr_get(rs, NFT_RULESET_ATTR_CHAINLIST);
+ ci = nft_chain_list_iter_create(cl);
+ if (ci == NULL)
+ memory_allocation_error();
+
+ c = nft_chain_list_iter_next(ci);
+ while (c != NULL) {
+ nft_chain_attr_unset(c, NFT_CHAIN_ATTR_HANDLE);
+ c = nft_chain_list_iter_next(ci);
+ }
+ nft_chain_list_iter_destroy(ci);
+ }
+
+ if (nft_ruleset_attr_is_set(rs, NFT_RULESET_ATTR_RULELIST)) {
+ reverse_rule_list = nft_rule_list_alloc();
+ if (reverse_rule_list == NULL)
+ memory_allocation_error();
+
+ rl = (struct nft_rule_list *)
+ nft_ruleset_attr_get(rs, NFT_RULESET_ATTR_RULELIST);
+
+ ri = nft_rule_list_iter_create(rl);
+ if (ri == NULL)
+ memory_allocation_error();
+
+ r = nft_rule_list_iter_next(ri);
+ while (r != NULL) {
+ nft_rule_attr_unset(r, NFT_RULE_ATTR_HANDLE);
+ nft_rule_attr_unset(r, NFT_RULE_ATTR_POSITION);
+ nft_rule_list_del(r);
+ nft_rule_list_add(r, reverse_rule_list);
+ r = nft_rule_list_iter_next(ri);
+ }
+ nft_rule_list_iter_destroy(ri);
+
+ nft_ruleset_attr_set(rs, NFT_RULESET_ATTR_RULELIST,
+ reverse_rule_list);
+ }
+}
+
+int netlink_add_ruleset(struct netlink_ctx *ctx, const struct location *loc,
+ struct nft_ruleset *rs)
+{
+ int ret;
+
+ mnl_batch_init();
+ mnl_batch_begin();
+
+ /* We need some makeup:
+ * - unset chain handles
+ * - unset rule handles and positions
+ * - reverse the rule list
+ */
+ ruleset_setup(rs);
+
+ ret = mnl_nft_ruleset_add(nf_sock, rs, 0, 0, NLM_F_EXCL | NLM_F_ECHO,
+ 0, 0);
+ if (ret != 0)
+ return netlink_io_error(ctx, loc,
+ "Could not add ruleset:"
+ " %s", strerror(errno));
+ return ret;
+}
diff --git a/src/parser.y b/src/parser.y
index bb8e4d7..3d94635 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -175,6 +175,7 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%token RENAME "rename"
%token DESCRIBE "describe"
%token EXPORT "export"
+%token IMPORT "import"
%token ACCEPT "accept"
%token DROP "drop"
@@ -346,8 +347,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 insert_cmd delete_cmd list_cmd flush_cmd rename_cmd export_cmd
-%destructor { cmd_free($$); } base_cmd add_cmd insert_cmd delete_cmd list_cmd flush_cmd rename_cmd export_cmd
+%type <cmd> base_cmd add_cmd insert_cmd delete_cmd list_cmd flush_cmd rename_cmd export_cmd import_cmd
+%destructor { cmd_free($$); } base_cmd add_cmd insert_cmd delete_cmd list_cmd flush_cmd rename_cmd export_cmd import_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
@@ -467,8 +468,7 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%destructor { expr_free($$); } ct_expr
%type <val> ct_key
-%type <val> export_format
-
+%type <val> export_format import_format
%%
input : /* empty */
@@ -537,6 +537,7 @@ base_cmd : /* empty */ add_cmd { $$ = $1; }
| FLUSH flush_cmd { $$ = $2; }
| RENAME rename_cmd { $$ = $2; }
| EXPORT export_cmd { $$ = $2; }
+ | IMPORT import_cmd { $$ = $2; }
| DESCRIBE primary_expr
{
expr_describe($2);
@@ -679,6 +680,15 @@ export_cmd : export_format
}
;
+
+import_cmd : import_format
+ {
+ struct handle h = { .family = NFPROTO_UNSPEC };
+ $$ = cmd_alloc(CMD_IMPORT, CMD_OBJ_RULESET, &h, &@$, NULL);
+ $$->format = $1;
+ }
+ ;
+
table_block_alloc : /* empty */
{
$$ = table_alloc();
@@ -1843,6 +1853,9 @@ mh_hdr_field : NEXTHDR { $$ = MHHDR_NEXTHDR; }
| CHECKSUM { $$ = MHHDR_CHECKSUM; }
;
+import_format : export_format
+ ;
+
export_format : XML { $$ = NFT_OUTPUT_XML; }
| JSON { $$ = NFT_OUTPUT_JSON; }
;
diff --git a/src/rule.c b/src/rule.c
index f83f545..7a426f0 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -19,6 +19,7 @@
#include <rule.h>
#include <utils.h>
#include <netlink.h>
+#include <mnl.h>
#include <libnftnl/common.h>
#include <libnftnl/ruleset.h>
@@ -602,6 +603,53 @@ static int do_command_export(struct netlink_ctx *ctx, struct cmd *cmd)
return 0;
}
+static int do_command_import(struct netlink_ctx *ctx, struct cmd *cmd)
+{
+ struct nft_ruleset *rs;
+ struct nft_parse_err *err;
+
+ rs = nft_ruleset_alloc();
+ if (rs == NULL)
+ memory_allocation_error();
+
+ err = nft_parse_err_alloc();
+ if (err == NULL)
+ memory_allocation_error();
+
+ if (nft_ruleset_parse_file(rs, cmd->format, stdin, err) < 0) {
+ nft_parse_perror("Unable to parse file", err);
+ goto err;
+ }
+
+#ifdef DEBUG
+ if (debug_level & DEBUG_NETLINK)
+ fprintf(stdout, "Ruleset parsing OK.\n");
+#endif
+
+ if (netlink_wipe_ruleset(ctx, &cmd->handle, &cmd->location) < 0)
+ goto err;
+#ifdef DEBUG
+ if (debug_level & DEBUG_NETLINK)
+ fprintf(stdout, "Kernel ruleset wipe OK.\n");
+#endif
+
+ if (netlink_add_ruleset(ctx, &cmd->location, rs) < 0)
+ goto err;
+
+#ifdef DEBUG
+ if (debug_level & DEBUG_NETLINK)
+ fprintf(stdout, "New ruleset added to kernel (without rules).\n");
+#endif
+
+ nft_ruleset_free(rs);
+ nft_parse_err_free(err);
+ return 0;
+err:
+ nft_ruleset_free(rs);
+ nft_parse_err_free(err);
+ return -1;
+}
+
static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd)
{
struct table *table = NULL;
@@ -754,6 +802,8 @@ int do_command(struct netlink_ctx *ctx, struct cmd *cmd)
return do_command_rename(ctx, cmd);
case CMD_EXPORT:
return do_command_export(ctx, cmd);
+ case CMD_IMPORT:
+ return do_command_import(ctx, cmd);
default:
BUG("invalid command object type %u\n", cmd->obj);
}
diff --git a/src/scanner.l b/src/scanner.l
index 69f238d..5f74916 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -254,6 +254,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"flush" { return FLUSH; }
"rename" { return RENAME; }
"export" { return EXPORT; }
+"import" { return IMPORT; }
"position" { return POSITION; }
next reply other threads:[~2014-01-21 17:02 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-01-21 17:02 Arturo Borrero Gonzalez [this message]
2014-01-21 17:22 ` [nft RFC PATCH] src: add import operation Patrick McHardy
2014-01-21 17:32 ` Patrick McHardy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20140121170211.31038.31659.stgit@nfdev.cica.es \
--to=arturo.borrero.glez@gmail.com \
--cc=kaber@trash.net \
--cc=netfilter-devel@vger.kernel.org \
--cc=pablo@netfilter.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.