Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/803561/?format=api
{ "id": 803561, "url": "http://patchwork.ozlabs.org/api/patches/803561/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netfilter-devel/patch/1503146400-12552-1-git-send-email-mayhs11saini@gmail.com/", "project": { "id": 26, "url": "http://patchwork.ozlabs.org/api/projects/26/?format=api", "name": "Netfilter Development", "link_name": "netfilter-devel", "list_id": "netfilter-devel.vger.kernel.org", "list_email": "netfilter-devel@vger.kernel.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<1503146400-12552-1-git-send-email-mayhs11saini@gmail.com>", "list_archive_url": null, "date": "2017-08-19T12:40:00", "name": "[RFC] src: Add import command for json", "commit_ref": null, "pull_url": null, "state": "changes-requested", "archived": false, "hash": "e5ebd2aa9911f623b0e825a334ca9f6aa4bf46e0", "submitter": { "id": 69683, "url": "http://patchwork.ozlabs.org/api/people/69683/?format=api", "name": "Shyam Saini", "email": "mayhs11saini@gmail.com" }, "delegate": { "id": 6139, "url": "http://patchwork.ozlabs.org/api/users/6139/?format=api", "username": "pablo", "first_name": "Pablo", "last_name": "Neira", "email": "pablo@netfilter.org" }, "mbox": "http://patchwork.ozlabs.org/project/netfilter-devel/patch/1503146400-12552-1-git-send-email-mayhs11saini@gmail.com/mbox/", "series": [], "comments": "http://patchwork.ozlabs.org/api/patches/803561/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/803561/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<netfilter-devel-owner@vger.kernel.org>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org", "Authentication-Results": [ "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=netfilter-devel-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)", "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"GRR1mZih\"; dkim-atps=neutral" ], "Received": [ "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xZKKx3Lz9z9s75\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSat, 19 Aug 2017 22:40:21 +1000 (AEST)", "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1751118AbdHSMkU (ORCPT <rfc822;incoming@patchwork.ozlabs.org>);\n\tSat, 19 Aug 2017 08:40:20 -0400", "from mail-pf0-f194.google.com ([209.85.192.194]:36290 \"EHLO\n\tmail-pf0-f194.google.com\" rhost-flags-OK-OK-OK-OK) by vger.kernel.org\n\twith ESMTP id S1751107AbdHSMkT (ORCPT\n\t<rfc822;netfilter-devel@vger.kernel.org>);\n\tSat, 19 Aug 2017 08:40:19 -0400", "by mail-pf0-f194.google.com with SMTP id t83so2929913pfj.3\n\tfor <netfilter-devel@vger.kernel.org>;\n\tSat, 19 Aug 2017 05:40:18 -0700 (PDT)", "from localhost.localdomain ([47.31.15.175])\n\tby smtp.gmail.com with ESMTPSA id\n\tp5sm14535803pgf.50.2017.08.19.05.40.15\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128);\n\tSat, 19 Aug 2017 05:40:17 -0700 (PDT)" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=gmail.com; s=20161025;\n\th=from:to:cc:subject:date:message-id;\n\tbh=0IPhtWGl0SgpkmnpJbmtGw7RZHRxCy+DfY+3KPUI6J8=;\n\tb=GRR1mZihMfcvGbXVY2Fam3IXbhBhPEqUxzYvxDI+kUVfAiWvhBt5MsmQQm0vGART/8\n\t7f6oosGBR69YFVZ0rjn6Bl8lwq4GeCD/9t10DeBW1JS5lFtGgH1zfWMIHVKpwmYHxoEH\n\tfzd3rUKvKv4azn/2j+3KE1dtqmpBAC0frpRCvDglHT0lo6N9nkV7vcwTDoVCaD3hvXiq\n\t8TiTJCNaKYmEq5tfir352ZIFun0jsOIKmul2zhS7Q6fDk9dt6Cwk+5bW2lsBwdNvcBj2\n\t/xMx7AVgb9vLPk8ojFYtd2jxjGfbokbxl5k+e6J8R9VLsMHooaVUHkYx/hKshJOH9taN\n\trW5A==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id;\n\tbh=0IPhtWGl0SgpkmnpJbmtGw7RZHRxCy+DfY+3KPUI6J8=;\n\tb=ITchzfnSpk4UD4xccbX+PUwALjOiBV5CdrzdPtQ/5o0Wdp296eu6hHqF7PcYlwmdMS\n\tjdqfKsX6DkKWIpYpxSlts3/pguyKe6cbs7z6AoUcQh0qwJ3kr7VkgDtMLmJTCpHkLUsz\n\tD1ejfgSTa46iaZ/4/KLijquKpYp5egLTpWddrDM2QT4liLfbmU/pJXSuSrV2tRFC4tqO\n\t2jaFJbCPF7f9x2ffBZCSqhfNefl/tAaJWaFCe/iVCq+tsOQ27nIY7HPPFaV5foNYs4YO\n\tRgcngrA07y0LYCgHTaQr0EFgIuAMZIYDvf0ZiAqlwuWJkIy3WcPhzn8+55ZS0PO10JEV\n\tJhLw==", "X-Gm-Message-State": "AHYfb5g9eNyUSrjOKegHsto5SX7RM55YNB2cVPKlHnFmSgzWMEXVfD5Y\n\tG0Xyk5OdjYhIzZaaNtA=", "X-Received": "by 10.101.70.15 with SMTP id v15mr11398804pgq.229.1503146418130; \n\tSat, 19 Aug 2017 05:40:18 -0700 (PDT)", "From": "Shyam Saini <mayhs11saini@gmail.com>", "To": "netfilter-devel@vger.kernel.org", "Cc": "pablo@netfilter.org, Shyam Saini <mayhs11saini@gmail.com>", "Subject": "[RFC PATCH] src: Add import command for json", "Date": "Sat, 19 Aug 2017 18:10:00 +0530", "Message-Id": "<1503146400-12552-1-git-send-email-mayhs11saini@gmail.com>", "X-Mailer": "git-send-email 1.9.1", "Sender": "netfilter-devel-owner@vger.kernel.org", "Precedence": "bulk", "List-ID": "<netfilter-devel.vger.kernel.org>", "X-Mailing-List": "netfilter-devel@vger.kernel.org" }, "content": "This new operation allows to import ruleset in json to make\nincremental changes using the parse functions of libnftnl.\n\nA basic way to test this new functionality is:\n\n % cat file.json | nft import json\n\nwhere the file.json is a ruleset exported in json format.\n\nHighly based on work from Alvaro Neira <alvaroneay@gmail.com>\nand Arturo Borrero <arturo@netfilter.org>.\n\nSigned-off-by: Shyam Saini <mayhs11saini@gmail.com>\n---\n include/netlink.h | 9 ++\n include/rule.h | 14 +--\n src/evaluate.c | 10 +-\n src/netlink.c | 279 +++++++++++++++++++++++++++++++++++++++++++++++++++++\n src/parser_bison.y | 38 +++++---\n src/rule.c | 44 +++++++--\n src/scanner.l | 1 +\n 7 files changed, 367 insertions(+), 28 deletions(-)", "diff": "diff --git a/include/netlink.h b/include/netlink.h\nindex 5b43c5c725ef..ea1b7a9b95be 100644\n--- a/include/netlink.h\n+++ b/include/netlink.h\n@@ -221,4 +221,13 @@ struct netlink_mon_handler {\n extern int netlink_monitor(struct netlink_mon_handler *monhandler);\n bool netlink_batch_supported(struct mnl_socket *nf_sock);\n \n+struct ruleset_parse {\n+ struct netlink_ctx *nl_ctx;\n+ struct cmd *cmd;\n+};\n+\n+struct nftnl_parse_ctx;\n+\n+int netlink_markup_parse_cb(const struct nftnl_parse_ctx *ctx);\n+\n #endif /* NFTABLES_NETLINK_H */\ndiff --git a/include/rule.h b/include/rule.h\nindex ddad6d40470e..1ea0a0f0f42e 100644\n--- a/include/rule.h\n+++ b/include/rule.h\n@@ -315,6 +315,7 @@ uint32_t obj_type_to_cmd(uint32_t type);\n * @CMD_RESET:\t\treset container\n * @CMD_FLUSH:\t\tflush container\n * @CMD_RENAME:\t\trename object\n+ * @CMD_IMPORT: import a ruleset in a given format\n * @CMD_EXPORT:\t\texport the ruleset in a given format\n * @CMD_MONITOR:\tevent listener\n * @CMD_DESCRIBE:\tdescribe an expression\n@@ -330,6 +331,7 @@ enum cmd_ops {\n \tCMD_RESET,\n \tCMD_FLUSH,\n \tCMD_RENAME,\n+\tCMD_IMPORT,\n \tCMD_EXPORT,\n \tCMD_MONITOR,\n \tCMD_DESCRIBE,\n@@ -349,7 +351,7 @@ enum cmd_ops {\n * @CMD_OBJ_RULESET:\truleset\n * @CMD_OBJ_EXPR:\texpression\n * @CMD_OBJ_MONITOR:\tmonitor\n- * @CMD_OBJ_EXPORT:\texport\n+ * @CMD_OBJ_MARKUP:\timport/export\n * @CMD_OBJ_COUNTER:\tcounter\n * @CMD_OBJ_COUNTERS:\tmultiple counters\n * @CMD_OBJ_QUOTA:\tquota\n@@ -367,7 +369,7 @@ enum cmd_obj {\n \tCMD_OBJ_RULESET,\n \tCMD_OBJ_EXPR,\n \tCMD_OBJ_MONITOR,\n-\tCMD_OBJ_EXPORT,\n+\tCMD_OBJ_MARKUP,\n \tCMD_OBJ_FLOWTABLE,\n \tCMD_OBJ_FLOWTABLES,\n \tCMD_OBJ_MAP,\n@@ -380,12 +382,12 @@ enum cmd_obj {\n \tCMD_OBJ_CT_HELPERS,\n };\n \n-struct export {\n+struct markup {\n \tuint32_t\tformat;\n };\n \n-struct export *export_alloc(uint32_t format);\n-void export_free(struct export *e);\n+struct markup *markup_alloc(uint32_t format);\n+void markup_free(struct markup *m);\n \n enum {\n \tCMD_MONITOR_OBJ_ANY,\n@@ -436,7 +438,7 @@ struct cmd {\n \t\tstruct chain\t*chain;\n \t\tstruct table\t*table;\n \t\tstruct monitor\t*monitor;\n-\t\tstruct export\t*export;\n+\t\tstruct markup\t*markup;\n \t\tstruct obj\t*object;\n \t};\n \tconst void\t\t*arg;\ndiff --git a/src/evaluate.c b/src/evaluate.c\nindex 27feef432ccf..b2e4a26ba44d 100644\n--- a/src/evaluate.c\n+++ b/src/evaluate.c\n@@ -3302,12 +3302,18 @@ static int cmd_evaluate_monitor(struct eval_ctx *ctx, struct cmd *cmd)\n \tcmd->monitor->flags = monitor_flags[event][cmd->monitor->type];\n \treturn 0;\n }\n-\n+/*\n+static int cmd_evaluate_import(struct eval_ctx *ctx, struct cmd *cmd)\n+{\n+\treturn cache_update(ctx->nf_sock, cmd->op, ctx->msgs);\n+}\n+*/\n static int cmd_evaluate_export(struct eval_ctx *ctx, struct cmd *cmd)\n {\n \treturn cache_update(ctx->nf_sock, cmd->op, ctx->msgs);\n }\n \n+\n #ifdef DEBUG\n static const char *cmd_op_name[] = {\n \t[CMD_INVALID]\t= \"invalid\",\n@@ -3368,6 +3374,8 @@ int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd)\n \t\treturn 0;\n \tcase CMD_MONITOR:\n \t\treturn cmd_evaluate_monitor(ctx, cmd);\n+\tcase CMD_IMPORT:\n+\t\treturn 0;\n \tdefault:\n \t\tBUG(\"invalid command operation %u\\n\", cmd->op);\n \t};\ndiff --git a/src/netlink.c b/src/netlink.c\nindex e3c90dac8c7a..5e7f98a1f046 100644\n--- a/src/netlink.c\n+++ b/src/netlink.c\n@@ -24,6 +24,7 @@\n #include <libnftnl/object.h>\n #include <libnftnl/set.h>\n #include <libnftnl/udata.h>\n+#include <libnftnl/ruleset.h>\n #include <libnftnl/common.h>\n #include <linux/netfilter/nfnetlink.h>\n #include <linux/netfilter/nf_tables.h>\n@@ -2976,6 +2977,284 @@ int netlink_monitor(struct netlink_mon_handler *monhandler)\n \t\t\t\t monhandler);\n }\n \n+static int netlink_markup_setelems(const struct nftnl_parse_ctx *ctx)\n+{\n+\tconst struct ruleset_parse *rp;\n+\tstruct nftnl_set *set;\n+\tuint32_t cmd;\n+\tint ret = -1;\n+\n+\tset = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_SET);\n+\trp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA);\n+\n+\tcmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD);\n+\tswitch (cmd) {\n+\tcase NFTNL_CMD_ADD:\n+\t\tret = mnl_nft_setelem_batch_add(set, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tcase NFTNL_CMD_DELETE:\n+\t\tret = mnl_nft_setelem_batch_del(set, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tdefault:\n+\t\terrno = EOPNOTSUPP;\n+\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int netlink_markup_set(const struct nftnl_parse_ctx *ctx)\n+{\n+\tconst struct ruleset_parse *rp;\n+\tstruct nftnl_set *set;\n+\tuint32_t cmd;\n+\tint ret = -1;\n+\n+\tset = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_SET);\n+\trp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA);\n+\n+\tcmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD);\n+\tswitch (cmd) {\n+\tcase NFTNL_CMD_ADD:\n+\t\tret = mnl_nft_set_batch_add(set, rp->nl_ctx->batch, NLM_F_EXCL,\n+\t\t\t\t\t rp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tcase NFTNL_CMD_DELETE:\n+\t\tret = mnl_nft_set_batch_del(set, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tdefault:\n+\t\terrno = EOPNOTSUPP;\n+\t\tbreak;\n+\t}\n+\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\treturn netlink_markup_setelems(ctx);\n+}\n+\n+static int netlink_markup_build_rule(const struct nftnl_parse_ctx *ctx,\n+\t\t\t\t uint32_t cmd, struct nftnl_rule *rule)\n+{\n+\tconst struct ruleset_parse *rp;\n+\tuint32_t nl_flags;\n+\tint ret = -1;\n+\n+\trp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA);\n+\n+\tswitch (cmd) {\n+\tcase NFTNL_CMD_ADD:\n+\t\tnl_flags = NLM_F_APPEND | NLM_F_CREATE;\n+\t\tnftnl_rule_unset(rule, NFTNL_RULE_HANDLE);\n+\t\tret = mnl_nft_rule_batch_add(rule, rp->nl_ctx->batch, nl_flags,\n+\t\t\t\t\t rp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tcase NFTNL_CMD_DELETE:\n+\t\tret = mnl_nft_rule_batch_del(rule, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tcase NFTNL_CMD_REPLACE:\n+\t\tnl_flags = NLM_F_REPLACE;\n+\t\tret = mnl_nft_rule_batch_add(rule, rp->nl_ctx->batch, nl_flags,\n+\t\t\t\t\t rp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tcase NFTNL_CMD_INSERT:\n+\t\tnl_flags = NLM_F_CREATE;\n+\t\tnftnl_rule_unset(rule, NFTNL_RULE_HANDLE);\n+\t\tret = mnl_nft_rule_batch_add(rule, rp->nl_ctx->batch, nl_flags,\n+\t\t\t\t\t rp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tdefault:\n+\t\terrno = EOPNOTSUPP;\n+\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int netlink_markup_rule(const struct nftnl_parse_ctx *ctx)\n+{\n+\tstruct nftnl_rule *rule;\n+\tuint32_t cmd;\n+\n+\tcmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD);\n+\trule = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_RULE);\n+\n+\treturn netlink_markup_build_rule(ctx, cmd, rule);\n+}\n+\n+static int netlink_markup_build_flush(const struct nftnl_parse_ctx *ctx)\n+{\n+\tstruct nftnl_rule *rule;\n+\tstruct nftnl_table *table;\n+\tstruct nftnl_chain *chain;\n+\tuint32_t type;\n+\tint ret = -1;\n+\n+\trule = nftnl_rule_alloc();\n+\tif (rule == NULL)\n+\t\treturn -1;\n+\n+\ttype = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_TYPE);\n+\tswitch (type) {\n+\tcase NFTNL_RULESET_TABLE:\n+\t\ttable = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_TABLE);\n+\n+\t\tnftnl_rule_set(rule, NFTNL_RULE_TABLE,\n+\t\t\t\t nftnl_table_get(table,\n+\t\t\t\t\t\t NFTNL_TABLE_NAME));\n+\t\tnftnl_rule_set(rule, NFTNL_RULE_FAMILY,\n+\t\t\t\t nftnl_table_get(table,\n+\t\t\t\t\t\t NFTNL_TABLE_FAMILY));\n+\t\tbreak;\n+\tcase NFTNL_RULESET_CHAIN:\n+\t\tchain = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_CHAIN);\n+\n+\t\tnftnl_rule_set(rule, NFTNL_RULE_TABLE,\n+\t\t\t\t nftnl_chain_get(chain,\n+\t\t\t\t\t\t NFTNL_CHAIN_TABLE));\n+\t\tnftnl_rule_set(rule, NFTNL_RULE_CHAIN,\n+\t\t\t\t nftnl_chain_get(chain,\n+\t\t\t\t\t\t NFTNL_CHAIN_NAME));\n+\t\tnftnl_rule_set(rule, NFTNL_RULE_FAMILY,\n+\t\t\t\t nftnl_chain_get(chain,\n+\t\t\t\t\t\t NFTNL_TABLE_FAMILY));\n+\t\tbreak;\n+\tdefault:\n+\t\terrno = EOPNOTSUPP;\n+\t\tgoto err;\n+\t}\n+\n+\tret = netlink_markup_build_rule(ctx, NFTNL_CMD_DELETE, rule);\n+err:\n+\tnftnl_rule_free(rule);\n+\treturn ret;\n+}\n+\n+static int netlink_markup_chain(const struct nftnl_parse_ctx *ctx)\n+{\n+\tconst struct ruleset_parse *rp;\n+\tstruct nftnl_chain *chain;\n+\tuint32_t cmd;\n+\tint ret = -1;\n+\n+\tchain = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_CHAIN);\n+\trp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA);\n+\n+\tnftnl_chain_unset(chain, NFTNL_CHAIN_HANDLE);\n+\n+\tcmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD);\n+\tswitch (cmd) {\n+\tcase NFTNL_CMD_ADD:\n+\t\tret = mnl_nft_chain_batch_add(chain, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tcase NFTNL_CMD_DELETE:\n+\t\tret = mnl_nft_chain_batch_del(chain, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tcase NFTNL_CMD_FLUSH:\n+\t\tret = netlink_markup_build_flush(ctx);\n+\t\tbreak;\n+\tdefault:\n+\t\terrno = EOPNOTSUPP;\n+\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int netlink_markup_build_table(const struct nftnl_parse_ctx *ctx,\n+\t\t\t\t uint32_t cmd, struct nftnl_table *table)\n+{\n+\tstruct ruleset_parse *rp;\n+\tint ret = -1;\n+\n+\trp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA);\n+\n+\tswitch (cmd) {\n+\tcase NFTNL_CMD_ADD:\n+\t\tret = mnl_nft_table_batch_add(table, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tcase NFTNL_CMD_DELETE:\n+\t\tret = mnl_nft_table_batch_del(table, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tcase NFTNL_CMD_FLUSH:\n+\t\tret = netlink_markup_build_flush(ctx);\n+\t\tbreak;\n+\tdefault:\n+\t\terrno = EOPNOTSUPP;\n+\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+\n+}\n+\n+static int netlink_markup_table(const struct nftnl_parse_ctx *ctx)\n+{\n+\tstruct nftnl_table *table;\n+\tuint32_t cmd;\n+\n+\tcmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD);\n+\ttable = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_TABLE);\n+\n+\treturn netlink_markup_build_table(ctx, cmd, table);\n+}\n+\n+static int netlink_markup_flush(const struct nftnl_parse_ctx *ctx)\n+{\n+\tstruct nftnl_table *table;\n+\tint ret;\n+\n+\ttable = nftnl_table_alloc();\n+\tif (table == NULL)\n+\t\treturn -1;\n+\n+\tret = netlink_markup_build_table(ctx, NFTNL_CMD_DELETE, table);\n+\tnftnl_table_free(table);\n+\n+\treturn ret;\n+}\n+\n+int netlink_markup_parse_cb(const struct nftnl_parse_ctx *ctx)\n+{\n+\tstruct ruleset_parse *rp;\n+\tuint32_t type;\n+\tint ret = -1;\n+\n+\trp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA);\n+\n+\ttype = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_TYPE);\n+\tswitch (type) {\n+\tcase NFTNL_RULESET_TABLE:\n+\t\tret = netlink_markup_table(ctx);\n+\t\tbreak;\n+\tcase NFTNL_RULESET_CHAIN:\n+\t\tret = netlink_markup_chain(ctx);\n+\t\tbreak;\n+\tcase NFTNL_RULESET_RULE:\n+\t\tret = netlink_markup_rule(ctx);\n+\t\tbreak;\n+\tcase NFTNL_RULESET_SET:\n+\t\tret = netlink_markup_set(ctx);\n+\t\tbreak;\n+\tcase NFTNL_RULESET_SET_ELEMS:\n+\t\tret = netlink_markup_setelems(ctx);\n+\t\tbreak;\n+\tcase NFTNL_RULESET_RULESET:\n+\t\tret = netlink_markup_flush(ctx);\n+\t\tbreak;\n+\tdefault:\n+\t\terrno = EOPNOTSUPP;\n+\t\tbreak;\n+\t}\n+\tnftnl_ruleset_ctx_free(ctx);\n+\n+\tif (ret < 0)\n+\t\tnetlink_io_error(rp->nl_ctx, &rp->cmd->location,\n+\t\t\t\t \"Could not import: %s\", strerror(errno));\n+\n+\treturn 0;\n+}\n+\n bool netlink_batch_supported(struct mnl_socket *nf_sock)\n {\n \treturn mnl_batch_supported(nf_sock);\ndiff --git a/src/parser_bison.y b/src/parser_bison.y\nindex 45b1dc9f9407..7875bba71325 100644\n--- a/src/parser_bison.y\n+++ b/src/parser_bison.y\n@@ -209,6 +209,7 @@ static void location_update(struct location *loc, struct location *rhs, int n)\n %token FLUSH\t\t\t\"flush\"\n %token RENAME\t\t\t\"rename\"\n %token DESCRIBE\t\t\t\"describe\"\n+%token IMPORT\t\t\t\"import\"\n %token EXPORT\t\t\t\"export\"\n %token MONITOR\t\t\t\"monitor\"\n \n@@ -470,8 +471,8 @@ static void location_update(struct location *loc, struct location *rhs, int n)\n %type <cmd>\t\t\tline\n %destructor { cmd_free($$); }\tline\n \n-%type <cmd>\t\t\tbase_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd list_cmd reset_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd\n-%destructor { cmd_free($$); }\tbase_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd list_cmd reset_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd\n+%type <cmd>\t\t\tbase_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd list_cmd reset_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd import_cmd\n+%destructor { cmd_free($$); }\tbase_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd list_cmd reset_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd import_cmd\n \n %type <handle>\t\t\ttable_spec chain_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec\n %destructor { handle_free(&$$); } table_spec chain_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec\n@@ -650,7 +651,7 @@ static void location_update(struct location *loc, struct location *rhs, int n)\n %destructor { expr_free($$); }\tfib_expr\n %type <val>\t\t\tfib_tuple\tfib_result\tfib_flag\n \n-%type <val>\t\t\texport_format\n+%type <val>\t\t\tmarkup_format\n %type <string>\t\t\tmonitor_event\n %destructor { xfree($$); }\tmonitor_event\n %type <val>\t\t\tmonitor_object\tmonitor_format\n@@ -778,6 +779,7 @@ base_cmd\t\t:\t/* empty */\tadd_cmd\t\t{ $$ = $1; }\n \t\t\t|\tRESET\t\treset_cmd\t{ $$ = $2; }\n \t\t\t|\tFLUSH\t\tflush_cmd\t{ $$ = $2; }\n \t\t\t|\tRENAME\t\trename_cmd\t{ $$ = $2; }\n+\t\t\t| IMPORT import_cmd { $$ = $2; }\n \t\t\t|\tEXPORT\t\texport_cmd\t{ $$ = $2; }\n \t\t\t|\tMONITOR\t\tmonitor_cmd\t{ $$ = $2; }\n \t\t\t|\tDESCRIBE\tdescribe_cmd\t{ $$ = $2; }\n@@ -1162,17 +1164,31 @@ rename_cmd\t\t:\tCHAIN\t\tchain_spec\tidentifier\n \t\t\t}\n \t\t\t;\n \n-export_cmd\t\t:\tRULESET\t\texport_format\n+import_cmd\t\t\t: RULESET markup_format\n \t\t\t{\n \t\t\t\tstruct handle h = { .family = NFPROTO_UNSPEC };\n-\t\t\t\tstruct export *export = export_alloc($2);\n-\t\t\t\t$$ = cmd_alloc(CMD_EXPORT, CMD_OBJ_EXPORT, &h, &@$, export);\n+\t\t\t\tstruct markup *markup = markup_alloc($2);\n+\t\t\t\t$$ = cmd_alloc(CMD_IMPORT, CMD_OBJ_MARKUP, &h, &@$, markup);\n \t\t\t}\n-\t\t\t|\texport_format\n+\t\t\t|\tmarkup_format\n \t\t\t{\n \t\t\t\tstruct handle h = { .family = NFPROTO_UNSPEC };\n-\t\t\t\tstruct export *export = export_alloc($1);\n-\t\t\t\t$$ = cmd_alloc(CMD_EXPORT, CMD_OBJ_EXPORT, &h, &@$, export);\n+\t\t\t\tstruct markup *markup = markup_alloc($1);\n+\t\t\t\t$$ = cmd_alloc(CMD_IMPORT, CMD_OBJ_MARKUP, &h, &@$, markup);\n+\t\t\t}\n+\t\t\t;\n+\n+export_cmd\t\t:\tRULESET\t\tmarkup_format\n+\t\t\t{\n+\t\t\t\tstruct handle h = { .family = NFPROTO_UNSPEC };\n+\t\t\t\tstruct markup *markup = markup_alloc($2);\n+\t\t\t\t$$ = cmd_alloc(CMD_EXPORT, CMD_OBJ_MARKUP, &h, &@$, markup);\n+\t\t\t}\n+\t\t\t|\tmarkup_format\n+\t\t\t{\n+\t\t\t\tstruct handle h = { .family = NFPROTO_UNSPEC };\n+\t\t\t\tstruct markup *markup = markup_alloc($1);\n+\t\t\t\t$$ = cmd_alloc(CMD_EXPORT, CMD_OBJ_MARKUP, &h, &@$, markup);\n \t\t\t}\n \t\t\t;\n \n@@ -1198,10 +1214,10 @@ monitor_object\t\t:\t/* empty */\t{ $$ = CMD_MONITOR_OBJ_ANY; }\n \t\t\t;\n \n monitor_format\t\t:\t/* empty */\t{ $$ = NFTNL_OUTPUT_DEFAULT; }\n-\t\t\t|\texport_format\n+\t\t\t|\tmarkup_format\n \t\t\t;\n \n-export_format\t\t: \tXML \t\t{ $$ = NFTNL_OUTPUT_XML; }\n+markup_format\t\t: \tXML \t\t{ $$ = NFTNL_OUTPUT_XML; }\n \t\t\t|\tJSON\t\t{ $$ = NFTNL_OUTPUT_JSON; }\n \t\t\t;\n \ndiff --git a/src/rule.c b/src/rule.c\nindex 1d89feb9f192..a974d0595722 100644\n--- a/src/rule.c\n+++ b/src/rule.c\n@@ -894,19 +894,19 @@ void nft_cmd_expand(struct cmd *cmd)\n \t}\n }\n \n-struct export *export_alloc(uint32_t format)\n+struct markup *markup_alloc(uint32_t format)\n {\n-\tstruct export *export;\n+\tstruct markup *markup;\n \n-\texport = xmalloc(sizeof(struct export));\n-\texport->format = format;\n+\tmarkup = xmalloc(sizeof(struct markup));\n+\tmarkup->format = format;\n \n-\treturn export;\n+\treturn markup;\n }\n \n-void export_free(struct export *e)\n+void markup_free(struct markup *m)\n {\n-\txfree(e);\n+\txfree(m);\n }\n \n struct monitor *monitor_alloc(uint32_t format, uint32_t type, const char *event)\n@@ -953,8 +953,8 @@ void cmd_free(struct cmd *cmd)\n \t\tcase CMD_OBJ_MONITOR:\n \t\t\tmonitor_free(cmd->monitor);\n \t\t\tbreak;\n-\t\tcase CMD_OBJ_EXPORT:\n-\t\t\texport_free(cmd->export);\n+\t\tcase CMD_OBJ_MARKUP:\n+\t\t\tmarkup_free(cmd->markup);\n \t\t\tbreak;\n \t\tcase CMD_OBJ_COUNTER:\n \t\tcase CMD_OBJ_QUOTA:\n@@ -1121,13 +1121,35 @@ static int do_command_export(struct netlink_ctx *ctx, struct cmd *cmd)\n \t\t\treturn -1;\n \t} while (rs == NULL);\n \n-\tnftnl_ruleset_fprintf(stdout, rs, cmd->export->format, 0);\n+\tnftnl_ruleset_fprintf(stdout, rs, cmd->markup->format, NFTNL_OF_EVENT_NEW);\n \tfprintf(stdout, \"\\n\");\n \n \tnftnl_ruleset_free(rs);\n \treturn 0;\n }\n \n+static int do_command_import(struct netlink_ctx *ctx, struct cmd *cmd)\n+{\n+\tint ret;\n+\tstruct nftnl_parse_err *err;\n+\tstruct ruleset_parse rp = {\n+\t\t.nl_ctx = ctx,\n+\t\t.cmd = cmd\n+\t};\n+\n+\terr = nftnl_parse_err_alloc();\n+\tif (err == NULL)\n+\t\treturn -1;\n+\n+\tret = nftnl_ruleset_parse_file_cb(cmd->markup->format, stdin, err, &rp,\n+\t\t\t\t\t netlink_markup_parse_cb);\n+\tif (ret < 0)\n+\t\tnftnl_parse_perror(\"unable to import: parsing failed\", err);\n+\n+\tnftnl_parse_err_free(err);\n+\treturn ret;\n+}\n+\n static int do_list_table(struct netlink_ctx *ctx, struct cmd *cmd,\n \t\t\t struct table *table)\n {\n@@ -1705,6 +1727,8 @@ int do_command(struct netlink_ctx *ctx, struct cmd *cmd)\n \t\treturn do_command_flush(ctx, cmd);\n \tcase CMD_RENAME:\n \t\treturn do_command_rename(ctx, cmd);\n+\tcase CMD_IMPORT:\n+\t\treturn do_command_import(ctx, cmd);\n \tcase CMD_EXPORT:\n \t\treturn do_command_export(ctx, cmd);\n \tcase CMD_MONITOR:\ndiff --git a/src/scanner.l b/src/scanner.l\nindex 7d5437f123ce..594a93b09f1e 100644\n--- a/src/scanner.l\n+++ b/src/scanner.l\n@@ -272,6 +272,7 @@ addrstring\t({macaddr}|{ip4addr}|{ip6addr})\n \"reset\"\t\t\t{ return RESET; }\n \"flush\"\t\t\t{ return FLUSH; }\n \"rename\"\t\t{ return RENAME; }\n+\"import\" { return IMPORT; }\n \"export\"\t\t{ return EXPORT; }\n \"monitor\"\t\t{ return MONITOR; }\n \n", "prefixes": [ "RFC" ] }