[{"id":1751854,"web_url":"http://patchwork.ozlabs.org/comment/1751854/","msgid":"<CAOfkYf44S_-HSryKMpcgMQMUfidpn3GhVqJX1MsrxXaB5u-qCA@mail.gmail.com>","list_archive_url":null,"date":"2017-08-19T12:42:07","subject":"Re: [RFC PATCH] src: Add import command for json","submitter":{"id":69683,"url":"http://patchwork.ozlabs.org/api/people/69683/","name":"Shyam Saini","email":"mayhs11saini@gmail.com"},"content":"Here is the rules.json file which i tested.\n\n\nOn Sat, Aug 19, 2017 at 6:10 PM, Shyam Saini <mayhs11saini@gmail.com> wrote:\n> This new operation allows to import ruleset in json to make\n> incremental changes using the parse functions of libnftnl.\n>\n> A basic way to test this new functionality is:\n>\n>  % cat file.json | nft import json\n>\n> where the file.json is a ruleset exported in json format.\n>\n> Highly based on work from  Alvaro Neira <alvaroneay@gmail.com>\n> and Arturo Borrero <arturo@netfilter.org>.\n>\n> Signed-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(-)\n>\n> diff --git a/include/netlink.h b/include/netlink.h\n> index 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 */\n> diff --git a/include/rule.h b/include/rule.h\n> index 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:         reset container\n>   * @CMD_FLUSH:         flush container\n>   * @CMD_RENAME:                rename object\n> + * @CMD_IMPORT:         import a ruleset in a given format\n>   * @CMD_EXPORT:                export the ruleset in a given format\n>   * @CMD_MONITOR:       event listener\n>   * @CMD_DESCRIBE:      describe an expression\n> @@ -330,6 +331,7 @@ enum cmd_ops {\n>         CMD_RESET,\n>         CMD_FLUSH,\n>         CMD_RENAME,\n> +       CMD_IMPORT,\n>         CMD_EXPORT,\n>         CMD_MONITOR,\n>         CMD_DESCRIBE,\n> @@ -349,7 +351,7 @@ enum cmd_ops {\n>   * @CMD_OBJ_RULESET:   ruleset\n>   * @CMD_OBJ_EXPR:      expression\n>   * @CMD_OBJ_MONITOR:   monitor\n> - * @CMD_OBJ_EXPORT:    export\n> + * @CMD_OBJ_MARKUP:    import/export\n>   * @CMD_OBJ_COUNTER:   counter\n>   * @CMD_OBJ_COUNTERS:  multiple counters\n>   * @CMD_OBJ_QUOTA:     quota\n> @@ -367,7 +369,7 @@ enum cmd_obj {\n>         CMD_OBJ_RULESET,\n>         CMD_OBJ_EXPR,\n>         CMD_OBJ_MONITOR,\n> -       CMD_OBJ_EXPORT,\n> +       CMD_OBJ_MARKUP,\n>         CMD_OBJ_FLOWTABLE,\n>         CMD_OBJ_FLOWTABLES,\n>         CMD_OBJ_MAP,\n> @@ -380,12 +382,12 @@ enum cmd_obj {\n>         CMD_OBJ_CT_HELPERS,\n>  };\n>\n> -struct export {\n> +struct markup {\n>         uint32_t        format;\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>         CMD_MONITOR_OBJ_ANY,\n> @@ -436,7 +438,7 @@ struct cmd {\n>                 struct chain    *chain;\n>                 struct table    *table;\n>                 struct monitor  *monitor;\n> -               struct export   *export;\n> +               struct markup   *markup;\n>                 struct obj      *object;\n>         };\n>         const void              *arg;\n> diff --git a/src/evaluate.c b/src/evaluate.c\n> index 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>         cmd->monitor->flags = monitor_flags[event][cmd->monitor->type];\n>         return 0;\n>  }\n> -\n> +/*\n> +static int cmd_evaluate_import(struct eval_ctx *ctx, struct cmd *cmd)\n> +{\n> +       return 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>         return cache_update(ctx->nf_sock, cmd->op, ctx->msgs);\n>  }\n>\n> +\n>  #ifdef DEBUG\n>  static const char *cmd_op_name[] = {\n>         [CMD_INVALID]   = \"invalid\",\n> @@ -3368,6 +3374,8 @@ int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd)\n>                 return 0;\n>         case CMD_MONITOR:\n>                 return cmd_evaluate_monitor(ctx, cmd);\n> +       case CMD_IMPORT:\n> +               return 0;\n>         default:\n>                 BUG(\"invalid command operation %u\\n\", cmd->op);\n>         };\n> diff --git a/src/netlink.c b/src/netlink.c\n> index 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>                                       monhandler);\n>  }\n>\n> +static int netlink_markup_setelems(const struct nftnl_parse_ctx *ctx)\n> +{\n> +       const struct ruleset_parse *rp;\n> +       struct nftnl_set *set;\n> +       uint32_t cmd;\n> +       int ret = -1;\n> +\n> +       set = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_SET);\n> +       rp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA);\n> +\n> +       cmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD);\n> +       switch (cmd) {\n> +       case NFTNL_CMD_ADD:\n> +               ret = mnl_nft_setelem_batch_add(set, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n> +               break;\n> +       case NFTNL_CMD_DELETE:\n> +               ret = mnl_nft_setelem_batch_del(set, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n> +               break;\n> +       default:\n> +               errno = EOPNOTSUPP;\n> +               break;\n> +       }\n> +\n> +       return ret;\n> +}\n> +\n> +static int netlink_markup_set(const struct nftnl_parse_ctx *ctx)\n> +{\n> +       const struct ruleset_parse *rp;\n> +       struct nftnl_set *set;\n> +       uint32_t cmd;\n> +       int ret = -1;\n> +\n> +       set = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_SET);\n> +       rp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA);\n> +\n> +       cmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD);\n> +       switch (cmd) {\n> +       case NFTNL_CMD_ADD:\n> +               ret = mnl_nft_set_batch_add(set, rp->nl_ctx->batch, NLM_F_EXCL,\n> +                                           rp->nl_ctx->seqnum);\n> +               break;\n> +       case NFTNL_CMD_DELETE:\n> +               ret = mnl_nft_set_batch_del(set, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n> +               break;\n> +       default:\n> +               errno = EOPNOTSUPP;\n> +               break;\n> +       }\n> +\n> +       if (ret < 0)\n> +               return ret;\n> +\n> +       return netlink_markup_setelems(ctx);\n> +}\n> +\n> +static int netlink_markup_build_rule(const struct nftnl_parse_ctx *ctx,\n> +                                    uint32_t cmd, struct nftnl_rule *rule)\n> +{\n> +       const struct ruleset_parse *rp;\n> +       uint32_t nl_flags;\n> +       int ret = -1;\n> +\n> +       rp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA);\n> +\n> +       switch (cmd) {\n> +       case NFTNL_CMD_ADD:\n> +               nl_flags = NLM_F_APPEND | NLM_F_CREATE;\n> +               nftnl_rule_unset(rule, NFTNL_RULE_HANDLE);\n> +               ret = mnl_nft_rule_batch_add(rule, rp->nl_ctx->batch, nl_flags,\n> +                                            rp->nl_ctx->seqnum);\n> +               break;\n> +       case NFTNL_CMD_DELETE:\n> +               ret = mnl_nft_rule_batch_del(rule, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n> +               break;\n> +       case NFTNL_CMD_REPLACE:\n> +               nl_flags = NLM_F_REPLACE;\n> +               ret = mnl_nft_rule_batch_add(rule, rp->nl_ctx->batch, nl_flags,\n> +                                            rp->nl_ctx->seqnum);\n> +               break;\n> +       case NFTNL_CMD_INSERT:\n> +               nl_flags = NLM_F_CREATE;\n> +               nftnl_rule_unset(rule, NFTNL_RULE_HANDLE);\n> +               ret = mnl_nft_rule_batch_add(rule, rp->nl_ctx->batch, nl_flags,\n> +                                            rp->nl_ctx->seqnum);\n> +               break;\n> +       default:\n> +               errno = EOPNOTSUPP;\n> +               break;\n> +       }\n> +\n> +       return ret;\n> +}\n> +\n> +static int netlink_markup_rule(const struct nftnl_parse_ctx *ctx)\n> +{\n> +       struct nftnl_rule *rule;\n> +       uint32_t cmd;\n> +\n> +       cmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD);\n> +       rule = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_RULE);\n> +\n> +       return netlink_markup_build_rule(ctx, cmd, rule);\n> +}\n> +\n> +static int netlink_markup_build_flush(const struct nftnl_parse_ctx *ctx)\n> +{\n> +       struct nftnl_rule *rule;\n> +       struct nftnl_table *table;\n> +       struct nftnl_chain *chain;\n> +       uint32_t type;\n> +       int ret = -1;\n> +\n> +       rule = nftnl_rule_alloc();\n> +       if (rule == NULL)\n> +               return -1;\n> +\n> +       type = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_TYPE);\n> +       switch (type) {\n> +       case NFTNL_RULESET_TABLE:\n> +               table = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_TABLE);\n> +\n> +               nftnl_rule_set(rule, NFTNL_RULE_TABLE,\n> +                                 nftnl_table_get(table,\n> +                                                    NFTNL_TABLE_NAME));\n> +               nftnl_rule_set(rule, NFTNL_RULE_FAMILY,\n> +                                 nftnl_table_get(table,\n> +                                                    NFTNL_TABLE_FAMILY));\n> +               break;\n> +       case NFTNL_RULESET_CHAIN:\n> +               chain = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_CHAIN);\n> +\n> +               nftnl_rule_set(rule, NFTNL_RULE_TABLE,\n> +                                 nftnl_chain_get(chain,\n> +                                                    NFTNL_CHAIN_TABLE));\n> +               nftnl_rule_set(rule, NFTNL_RULE_CHAIN,\n> +                                 nftnl_chain_get(chain,\n> +                                                    NFTNL_CHAIN_NAME));\n> +               nftnl_rule_set(rule, NFTNL_RULE_FAMILY,\n> +                                 nftnl_chain_get(chain,\n> +                                                    NFTNL_TABLE_FAMILY));\n> +               break;\n> +       default:\n> +               errno = EOPNOTSUPP;\n> +               goto err;\n> +       }\n> +\n> +       ret = netlink_markup_build_rule(ctx, NFTNL_CMD_DELETE, rule);\n> +err:\n> +       nftnl_rule_free(rule);\n> +       return ret;\n> +}\n> +\n> +static int netlink_markup_chain(const struct nftnl_parse_ctx *ctx)\n> +{\n> +       const struct ruleset_parse *rp;\n> +       struct nftnl_chain *chain;\n> +       uint32_t cmd;\n> +       int ret = -1;\n> +\n> +       chain = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_CHAIN);\n> +       rp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA);\n> +\n> +       nftnl_chain_unset(chain, NFTNL_CHAIN_HANDLE);\n> +\n> +       cmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD);\n> +       switch (cmd) {\n> +       case NFTNL_CMD_ADD:\n> +               ret = mnl_nft_chain_batch_add(chain, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n> +               break;\n> +       case NFTNL_CMD_DELETE:\n> +               ret = mnl_nft_chain_batch_del(chain, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n> +               break;\n> +       case NFTNL_CMD_FLUSH:\n> +               ret = netlink_markup_build_flush(ctx);\n> +               break;\n> +       default:\n> +               errno = EOPNOTSUPP;\n> +               break;\n> +       }\n> +\n> +       return ret;\n> +}\n> +\n> +static int netlink_markup_build_table(const struct nftnl_parse_ctx *ctx,\n> +                                     uint32_t cmd, struct nftnl_table *table)\n> +{\n> +       struct ruleset_parse *rp;\n> +       int ret = -1;\n> +\n> +       rp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA);\n> +\n> +       switch (cmd) {\n> +       case NFTNL_CMD_ADD:\n> +               ret = mnl_nft_table_batch_add(table, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n> +               break;\n> +       case NFTNL_CMD_DELETE:\n> +               ret = mnl_nft_table_batch_del(table, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n> +               break;\n> +       case NFTNL_CMD_FLUSH:\n> +               ret = netlink_markup_build_flush(ctx);\n> +               break;\n> +       default:\n> +               errno = EOPNOTSUPP;\n> +               break;\n> +       }\n> +\n> +       return ret;\n> +\n> +}\n> +\n> +static int netlink_markup_table(const struct nftnl_parse_ctx *ctx)\n> +{\n> +       struct nftnl_table *table;\n> +       uint32_t cmd;\n> +\n> +       cmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD);\n> +       table = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_TABLE);\n> +\n> +       return netlink_markup_build_table(ctx, cmd, table);\n> +}\n> +\n> +static int netlink_markup_flush(const struct nftnl_parse_ctx *ctx)\n> +{\n> +       struct nftnl_table *table;\n> +       int ret;\n> +\n> +       table = nftnl_table_alloc();\n> +       if (table == NULL)\n> +               return -1;\n> +\n> +       ret = netlink_markup_build_table(ctx, NFTNL_CMD_DELETE, table);\n> +       nftnl_table_free(table);\n> +\n> +       return ret;\n> +}\n> +\n> +int netlink_markup_parse_cb(const struct nftnl_parse_ctx *ctx)\n> +{\n> +       struct ruleset_parse *rp;\n> +       uint32_t type;\n> +       int ret = -1;\n> +\n> +       rp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA);\n> +\n> +       type = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_TYPE);\n> +       switch (type) {\n> +       case NFTNL_RULESET_TABLE:\n> +               ret = netlink_markup_table(ctx);\n> +               break;\n> +       case NFTNL_RULESET_CHAIN:\n> +               ret = netlink_markup_chain(ctx);\n> +               break;\n> +       case NFTNL_RULESET_RULE:\n> +               ret = netlink_markup_rule(ctx);\n> +               break;\n> +       case NFTNL_RULESET_SET:\n> +               ret = netlink_markup_set(ctx);\n> +               break;\n> +       case NFTNL_RULESET_SET_ELEMS:\n> +               ret = netlink_markup_setelems(ctx);\n> +               break;\n> +       case NFTNL_RULESET_RULESET:\n> +               ret = netlink_markup_flush(ctx);\n> +               break;\n> +       default:\n> +               errno = EOPNOTSUPP;\n> +               break;\n> +       }\n> +       nftnl_ruleset_ctx_free(ctx);\n> +\n> +       if (ret < 0)\n> +               netlink_io_error(rp->nl_ctx, &rp->cmd->location,\n> +                                \"Could not import: %s\", strerror(errno));\n> +\n> +       return 0;\n> +}\n> +\n>  bool netlink_batch_supported(struct mnl_socket *nf_sock)\n>  {\n>         return mnl_batch_supported(nf_sock);\n> diff --git a/src/parser_bison.y b/src/parser_bison.y\n> index 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                   \"flush\"\n>  %token RENAME                  \"rename\"\n>  %token DESCRIBE                        \"describe\"\n> +%token IMPORT                  \"import\"\n>  %token EXPORT                  \"export\"\n>  %token MONITOR                 \"monitor\"\n>\n> @@ -470,8 +471,8 @@ static void location_update(struct location *loc, struct location *rhs, int n)\n>  %type <cmd>                    line\n>  %destructor { cmd_free($$); }  line\n>\n> -%type <cmd>                    base_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($$); }  base_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>                    base_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($$); }  base_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>                 table_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($$); } fib_expr\n>  %type <val>                    fib_tuple       fib_result      fib_flag\n>\n> -%type <val>                    export_format\n> +%type <val>                    markup_format\n>  %type <string>                 monitor_event\n>  %destructor { xfree($$); }     monitor_event\n>  %type <val>                    monitor_object  monitor_format\n> @@ -778,6 +779,7 @@ base_cmd            :       /* empty */     add_cmd         { $$ = $1; }\n>                         |       RESET           reset_cmd       { $$ = $2; }\n>                         |       FLUSH           flush_cmd       { $$ = $2; }\n>                         |       RENAME          rename_cmd      { $$ = $2; }\n> +                       |       IMPORT          import_cmd      { $$ = $2; }\n>                         |       EXPORT          export_cmd      { $$ = $2; }\n>                         |       MONITOR         monitor_cmd     { $$ = $2; }\n>                         |       DESCRIBE        describe_cmd    { $$ = $2; }\n> @@ -1162,17 +1164,31 @@ rename_cmd              :       CHAIN           chain_spec      identifier\n>                         }\n>                         ;\n>\n> -export_cmd             :       RULESET         export_format\n> +import_cmd                     :       RULESET         markup_format\n>                         {\n>                                 struct handle h = { .family = NFPROTO_UNSPEC };\n> -                               struct export *export = export_alloc($2);\n> -                               $$ = cmd_alloc(CMD_EXPORT, CMD_OBJ_EXPORT, &h, &@$, export);\n> +                               struct markup *markup = markup_alloc($2);\n> +                               $$ = cmd_alloc(CMD_IMPORT, CMD_OBJ_MARKUP, &h, &@$, markup);\n>                         }\n> -                       |       export_format\n> +                       |       markup_format\n>                         {\n>                                 struct handle h = { .family = NFPROTO_UNSPEC };\n> -                               struct export *export = export_alloc($1);\n> -                               $$ = cmd_alloc(CMD_EXPORT, CMD_OBJ_EXPORT, &h, &@$, export);\n> +                               struct markup *markup = markup_alloc($1);\n> +                               $$ = cmd_alloc(CMD_IMPORT, CMD_OBJ_MARKUP, &h, &@$, markup);\n> +                       }\n> +                       ;\n> +\n> +export_cmd             :       RULESET         markup_format\n> +                       {\n> +                               struct handle h = { .family = NFPROTO_UNSPEC };\n> +                               struct markup *markup = markup_alloc($2);\n> +                               $$ = cmd_alloc(CMD_EXPORT, CMD_OBJ_MARKUP, &h, &@$, markup);\n> +                       }\n> +                       |       markup_format\n> +                       {\n> +                               struct handle h = { .family = NFPROTO_UNSPEC };\n> +                               struct markup *markup = markup_alloc($1);\n> +                               $$ = cmd_alloc(CMD_EXPORT, CMD_OBJ_MARKUP, &h, &@$, markup);\n>                         }\n>                         ;\n>\n> @@ -1198,10 +1214,10 @@ monitor_object          :       /* empty */     { $$ = CMD_MONITOR_OBJ_ANY; }\n>                         ;\n>\n>  monitor_format         :       /* empty */     { $$ = NFTNL_OUTPUT_DEFAULT; }\n> -                       |       export_format\n> +                       |       markup_format\n>                         ;\n>\n> -export_format          :       XML             { $$ = NFTNL_OUTPUT_XML; }\n> +markup_format          :       XML             { $$ = NFTNL_OUTPUT_XML; }\n>                         |       JSON            { $$ = NFTNL_OUTPUT_JSON; }\n>                         ;\n>\n> diff --git a/src/rule.c b/src/rule.c\n> index 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>         }\n>  }\n>\n> -struct export *export_alloc(uint32_t format)\n> +struct markup *markup_alloc(uint32_t format)\n>  {\n> -       struct export *export;\n> +       struct markup *markup;\n>\n> -       export = xmalloc(sizeof(struct export));\n> -       export->format = format;\n> +       markup = xmalloc(sizeof(struct markup));\n> +       markup->format = format;\n>\n> -       return export;\n> +       return markup;\n>  }\n>\n> -void export_free(struct export *e)\n> +void markup_free(struct markup *m)\n>  {\n> -       xfree(e);\n> +       xfree(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>                 case CMD_OBJ_MONITOR:\n>                         monitor_free(cmd->monitor);\n>                         break;\n> -               case CMD_OBJ_EXPORT:\n> -                       export_free(cmd->export);\n> +               case CMD_OBJ_MARKUP:\n> +                       markup_free(cmd->markup);\n>                         break;\n>                 case CMD_OBJ_COUNTER:\n>                 case CMD_OBJ_QUOTA:\n> @@ -1121,13 +1121,35 @@ static int do_command_export(struct netlink_ctx *ctx, struct cmd *cmd)\n>                         return -1;\n>         } while (rs == NULL);\n>\n> -       nftnl_ruleset_fprintf(stdout, rs, cmd->export->format, 0);\n> +       nftnl_ruleset_fprintf(stdout, rs, cmd->markup->format, NFTNL_OF_EVENT_NEW);\n>         fprintf(stdout, \"\\n\");\n>\n>         nftnl_ruleset_free(rs);\n>         return 0;\n>  }\n>\n> +static int do_command_import(struct netlink_ctx *ctx, struct cmd *cmd)\n> +{\n> +       int ret;\n> +       struct nftnl_parse_err *err;\n> +       struct ruleset_parse rp = {\n> +               .nl_ctx = ctx,\n> +               .cmd    = cmd\n> +       };\n> +\n> +       err = nftnl_parse_err_alloc();\n> +       if (err == NULL)\n> +               return -1;\n> +\n> +       ret = nftnl_ruleset_parse_file_cb(cmd->markup->format, stdin, err, &rp,\n> +                                         netlink_markup_parse_cb);\n> +       if (ret < 0)\n> +               nftnl_parse_perror(\"unable to import: parsing failed\", err);\n> +\n> +       nftnl_parse_err_free(err);\n> +       return ret;\n> +}\n> +\n>  static int do_list_table(struct netlink_ctx *ctx, struct cmd *cmd,\n>                          struct table *table)\n>  {\n> @@ -1705,6 +1727,8 @@ int do_command(struct netlink_ctx *ctx, struct cmd *cmd)\n>                 return do_command_flush(ctx, cmd);\n>         case CMD_RENAME:\n>                 return do_command_rename(ctx, cmd);\n> +       case CMD_IMPORT:\n> +               return do_command_import(ctx, cmd);\n>         case CMD_EXPORT:\n>                 return do_command_export(ctx, cmd);\n>         case CMD_MONITOR:\n> diff --git a/src/scanner.l b/src/scanner.l\n> index 7d5437f123ce..594a93b09f1e 100644\n> --- a/src/scanner.l\n> +++ b/src/scanner.l\n> @@ -272,6 +272,7 @@ addrstring  ({macaddr}|{ip4addr}|{ip6addr})\n>  \"reset\"                        { return RESET; }\n>  \"flush\"                        { return FLUSH; }\n>  \"rename\"               { return RENAME; }\n> +\"import\"                { return IMPORT; }\n>  \"export\"               { return EXPORT; }\n>  \"monitor\"              { return MONITOR; }\n>\n> --\n> 1.9.1\n>","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=\"I1B8ujzw\"; dkim-atps=neutral"],"Received":["from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xZKN53wZLz9s75\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSat, 19 Aug 2017 22:42:13 +1000 (AEST)","(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1751307AbdHSMmM (ORCPT <rfc822;incoming@patchwork.ozlabs.org>);\n\tSat, 19 Aug 2017 08:42:12 -0400","from mail-oi0-f68.google.com ([209.85.218.68]:34133 \"EHLO\n\tmail-oi0-f68.google.com\" rhost-flags-OK-OK-OK-OK) by vger.kernel.org\n\twith ESMTP id S1751114AbdHSMmK (ORCPT\n\t<rfc822;netfilter-devel@vger.kernel.org>);\n\tSat, 19 Aug 2017 08:42:10 -0400","by mail-oi0-f68.google.com with SMTP id v11so11772076oif.1\n\tfor <netfilter-devel@vger.kernel.org>;\n\tSat, 19 Aug 2017 05:42:09 -0700 (PDT)","by 10.74.27.194 with HTTP; Sat, 19 Aug 2017 05:42:07 -0700 (PDT)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=gmail.com; s=20161025;\n\th=mime-version:in-reply-to:references:from:date:message-id:subject:to\n\t:cc; bh=bjPFCf6UmhcP4+S2rWnftvaEwj3aNHHTBCDn4gy/f24=;\n\tb=I1B8ujzw7aK+TGL8YlmBITxcRJMGF59n4maGikzUhZ5av4/ncr1jQoPBtsZnIIbfOy\n\tu2pZ84jYaaKctuIT//1kihHYkdcFXOlXgPnCBEA6Agtc5VwNDIx5KoGM5jY46R8YzuoW\n\tAPlQ3130cymYWyXA3ksLmypXRtg/QoA+0eQGPhfT4j+iqKwcIg6NobKtMg33g9b7y97U\n\tqWU3+l50+J2DQktTUtm+J7xp/0y3ohXARRXRovnDJ4ckTK0+ReHWPEoAV10yhLo9b0In\n\tKjKLfqV44EreJFkOh7eFqSgfzAxuA/l168+cb4GLiR0QObH5Lfph2+b74jLJbmXhj2+v\n\tuV4A==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:mime-version:in-reply-to:references:from:date\n\t:message-id:subject:to:cc;\n\tbh=bjPFCf6UmhcP4+S2rWnftvaEwj3aNHHTBCDn4gy/f24=;\n\tb=I26Qe87Eg/txIIoV9UuV4uqeHjYsXk6w3GMeW0EMCPU965ZPw5B73l2Xq4v844p2zs\n\t96246zk6Vu/mg275fMRujhA0fa/e7PZL3yIEMU6D16nI11CrMs36md+7AAUMM37bjXHb\n\teG6MCdGAAgQrB6FIf5kricHP7OcFnOlDU+36d6yJsVxKkniUcU5pYM+xri0eJ+ODOQvj\n\tj3ctDFNy0s3ezmj4Z2ywzln/BEIfsmN/Zy9RHlVV0cH8IpbLEdlomdFpyDDCjgIY761A\n\t1IYZHlwLKo6+JOAHm3zzhkEtWYb982teISx1vepgoHH91hYDhZ7kjVsKoOYfAaWbIIvv\n\t+FSA==","X-Gm-Message-State":"AHYfb5jFLByiTZSxbD50uLAHySQih9e9OQpkXgWFYUqbsoYIoKEmnI/C\n\tqSBYigqBfSf+pc5hvHwv7eAc6yKz/Q==","X-Received":"by 10.202.96.138 with SMTP id\n\tu132mr16705293oib.265.1503146529050; \n\tSat, 19 Aug 2017 05:42:09 -0700 (PDT)","MIME-Version":"1.0","In-Reply-To":"<1503146400-12552-1-git-send-email-mayhs11saini@gmail.com>","References":"<1503146400-12552-1-git-send-email-mayhs11saini@gmail.com>","From":"Shyam Saini <mayhs11saini@gmail.com>","Date":"Sat, 19 Aug 2017 18:12:07 +0530","Message-ID":"<CAOfkYf44S_-HSryKMpcgMQMUfidpn3GhVqJX1MsrxXaB5u-qCA@mail.gmail.com>","Subject":"Re: [RFC PATCH] src: Add import command for json","To":"Netfilter Development Mailing list <netfilter-devel@vger.kernel.org>","Cc":"Pablo Neira Ayuso <pablo@netfilter.org>,\n\tShyam Saini <mayhs11saini@gmail.com>","Content-Type":"multipart/mixed; boundary=\"001a113d5246e8f0d105571a92b0\"","Sender":"netfilter-devel-owner@vger.kernel.org","Precedence":"bulk","List-ID":"<netfilter-devel.vger.kernel.org>","X-Mailing-List":"netfilter-devel@vger.kernel.org"}}]