From patchwork Tue Dec 5 14:07:34 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shyam Saini X-Patchwork-Id: 844762 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Yy2hVYCj"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yrk9Y0T45z9t9j for ; Wed, 6 Dec 2017 01:08:17 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753121AbdLEOIP (ORCPT ); Tue, 5 Dec 2017 09:08:15 -0500 Received: from mail-pg0-f65.google.com ([74.125.83.65]:37213 "EHLO mail-pg0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752609AbdLEOHw (ORCPT ); Tue, 5 Dec 2017 09:07:52 -0500 Received: by mail-pg0-f65.google.com with SMTP id y6so213991pgp.4 for ; Tue, 05 Dec 2017 06:07:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=wM0+IZF1Rliy7NOqR17Qqd1uiBwDv23OZ0XrRsl1s8g=; b=Yy2hVYCjOtz4v+AzryGI2rrobe+mFbtdTFRxRuvSzaoNCvTfc3N9IR6SIEKoPjNsP4 AKcquL5PivCfHE9Yn1zPbHUpCGMp/yDB2LG5VYr6fbvNQrovJmwGEBWh6eerW5thEE/X e1n84yfVNKuQqs9pHR5RKCsW0Fixo231QlgdExhJ45qaDUehMKZ5iPtVIeZQ/WGNfBO7 DErv3TPiB3FQClIYiWMvx3Lwi8bqr8bdDP3AgXw/0LmMycV/TqmomexZ83OX59nw4M2s CWhh785q9Nl3gnEsw8Lm3ky3Aed36bDNbglnFgSc9gYIkgIclA3+a7ZU85cdTEqxFjCt pnwQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=wM0+IZF1Rliy7NOqR17Qqd1uiBwDv23OZ0XrRsl1s8g=; b=Ic9XlvmqXYO4H1BghWZIXKRbHWtWqVutlClnnRIeQjaWZmwckxIxxLj8y3yHey0UKw ne9iggepJ7cXp3efL++/odc6xuk4jvBWlGOP47ACHO3ikTRHJDx5iqRE4wnrjGB8faYn v50yaLM4tx+bH6nlyDAs9VVJIvQvKxWD0rj93FO1WP9zMt2ihfTyz+KyTYRomZhuTdhE 31G+arqEWaQRVW6gXpDhI9OKvk/NaDMHwmyg+1N9OQGXcihMIkQD4m+Gs8Bg4+BVuN2p /NXBqIoQ2kqY/67jrlBDqkXvyv/sNwDJQCSiUZi1bZ9f4EyuwKAM3Axlwp9nMqdK9u4N rwAA== X-Gm-Message-State: AKGB3mIsrY8Q818bp+XKSc7aRbV3NSo2Jc9FgChMQUJHNCPsyQJuLYxf 6QwKTlkXfbH4yIREz6Hm40jLzw== X-Google-Smtp-Source: AGs4zMaPtdEiBDfJJsWZ40CmGAJ0O5u/KbUXVEKoDa0IkPfl0XlD6nHCEPFMvd3MoaN6Tum5yynLHQ== X-Received: by 10.99.149.76 with SMTP id t12mr6656009pgn.382.1512482871410; Tue, 05 Dec 2017 06:07:51 -0800 (PST) Received: from administrator-ThinkPad-L450.one97.delhi.net ([203.122.38.200]) by smtp.gmail.com with ESMTPSA id b10sm520200pfj.20.2017.12.05.06.07.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 05 Dec 2017 06:07:50 -0800 (PST) From: Shyam Saini To: netfilter-devel@vger.kernel.org Cc: Shyam Saini Subject: [RFC PATCH nft V6 1/2] src: Add import command for low level json Date: Tue, 5 Dec 2017 19:37:34 +0530 Message-Id: <1512482855-29426-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: X-Mailing-List: netfilter-devel@vger.kernel.org This new operation allows to import low level virtual machine ruleset in json to make incremental changes using the parse functions of libnftnl. A basic way to test this new functionality is: $ cat file.json | nft import vm json where the file.json is a ruleset exported in low level json format. To export json rules in low level virtual machine format we need to specify "vm" token before json. See below $ nft export vm json and $ nft export/import json will do no operations. Same goes with "$nft monitor" Highly based on work from Alvaro Neira and Arturo Borrero Acked-by: Arturo Borrero Gonzalez Signed-off-by: Shyam Saini --- V6: Patch series Rebased V5: Adopt new "vm" symbol in the grammer which will be used to specify json format in low level virtual machine format. The defaut format will be high level json format which will come into exitence with upcoming high level library. With this patch "export/import json" does no operation --- include/netlink.h | 9 ++ include/rule.h | 14 +-- src/evaluate.c | 2 + src/netlink.c | 285 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/parser_bison.y | 44 ++++++--- src/rule.c | 46 +++++++-- src/scanner.l | 2 + 7 files changed, 374 insertions(+), 28 deletions(-) diff --git a/include/netlink.h b/include/netlink.h index 51cd5c9d1b94..66686e5a3313 100644 --- a/include/netlink.h +++ b/include/netlink.h @@ -225,4 +225,13 @@ bool netlink_batch_supported(struct mnl_socket *nf_sock, uint32_t *seqnum); int netlink_echo_callback(const struct nlmsghdr *nlh, void *data); +struct ruleset_parse { + struct netlink_ctx *nl_ctx; + struct cmd *cmd; +}; + +struct nftnl_parse_ctx; + +int netlink_markup_parse_cb(const struct nftnl_parse_ctx *ctx); + #endif /* NFTABLES_NETLINK_H */ diff --git a/include/rule.h b/include/rule.h index 4912aa168357..4e5a349a806a 100644 --- a/include/rule.h +++ b/include/rule.h @@ -326,6 +326,7 @@ uint32_t obj_type_to_cmd(uint32_t type); * @CMD_RESET: reset container * @CMD_FLUSH: flush container * @CMD_RENAME: rename object + * @CMD_IMPORT: import a ruleset in a given format * @CMD_EXPORT: export the ruleset in a given format * @CMD_MONITOR: event listener * @CMD_DESCRIBE: describe an expression @@ -341,6 +342,7 @@ enum cmd_ops { CMD_RESET, CMD_FLUSH, CMD_RENAME, + CMD_IMPORT, CMD_EXPORT, CMD_MONITOR, CMD_DESCRIBE, @@ -360,7 +362,7 @@ enum cmd_ops { * @CMD_OBJ_RULESET: ruleset * @CMD_OBJ_EXPR: expression * @CMD_OBJ_MONITOR: monitor - * @CMD_OBJ_EXPORT: export + * @CMD_OBJ_MARKUP: import/export * @CMD_OBJ_METER: meter * @CMD_OBJ_METERS: meters * @CMD_OBJ_COUNTER: counter @@ -382,7 +384,7 @@ enum cmd_obj { CMD_OBJ_RULESET, CMD_OBJ_EXPR, CMD_OBJ_MONITOR, - CMD_OBJ_EXPORT, + CMD_OBJ_MARKUP, CMD_OBJ_METER, CMD_OBJ_METERS, CMD_OBJ_MAP, @@ -397,12 +399,12 @@ enum cmd_obj { CMD_OBJ_LIMITS, }; -struct export { +struct markup { uint32_t format; }; -struct export *export_alloc(uint32_t format); -void export_free(struct export *e); +struct markup *markup_alloc(uint32_t format); +void markup_free(struct markup *m); enum { CMD_MONITOR_OBJ_ANY, @@ -454,7 +456,7 @@ struct cmd { struct chain *chain; struct table *table; struct monitor *monitor; - struct export *export; + struct markup *markup; struct obj *object; }; const void *arg; diff --git a/src/evaluate.c b/src/evaluate.c index 758e7bbe5939..742ac8fb64f2 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -3483,6 +3483,8 @@ int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd) return 0; case CMD_MONITOR: return cmd_evaluate_monitor(ctx, cmd); + case CMD_IMPORT: + return 0; default: BUG("invalid command operation %u\n", cmd->op); }; diff --git a/src/netlink.c b/src/netlink.c index 6735971ac1f3..61e574e41c78 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -3035,6 +3036,290 @@ int netlink_monitor(struct netlink_mon_handler *monhandler, monhandler); } +static int netlink_markup_setelems(const struct nftnl_parse_ctx *ctx) +{ + const struct ruleset_parse *rp; + struct nftnl_set *set; + uint32_t cmd; + int ret = -1; + + set = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_SET); + rp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA); + + cmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD); + switch (cmd) { + case NFTNL_CMD_ADD: + ret = mnl_nft_setelem_batch_add(set, rp->nl_ctx->batch, + 0, rp->nl_ctx->seqnum); + break; + case NFTNL_CMD_DELETE: + ret = mnl_nft_setelem_batch_del(set, rp->nl_ctx->batch, + 0, rp->nl_ctx->seqnum); + break; + default: + errno = EOPNOTSUPP; + break; + } + + return ret; +} + +static int netlink_markup_set(const struct nftnl_parse_ctx *ctx) +{ + const struct ruleset_parse *rp; + struct nftnl_set *set; + uint32_t cmd; + int ret = -1; + + set = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_SET); + rp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA); + + cmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD); + switch (cmd) { + case NFTNL_CMD_ADD: + ret = mnl_nft_set_batch_add(set, rp->nl_ctx->batch, NLM_F_EXCL, + rp->nl_ctx->seqnum); + break; + case NFTNL_CMD_DELETE: + ret = mnl_nft_set_batch_del(set, rp->nl_ctx->batch, + 0, rp->nl_ctx->seqnum); + break; + default: + errno = EOPNOTSUPP; + break; + } + + if (ret < 0) + return ret; + + return netlink_markup_setelems(ctx); +} + +static int netlink_markup_build_rule(const struct nftnl_parse_ctx *ctx, + uint32_t cmd, struct nftnl_rule *rule) +{ + const struct ruleset_parse *rp; + uint32_t nl_flags; + int ret = -1; + + rp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA); + + switch (cmd) { + case NFTNL_CMD_ADD: + nl_flags = NLM_F_APPEND | NLM_F_CREATE; + nftnl_rule_unset(rule, NFTNL_RULE_HANDLE); + ret = mnl_nft_rule_batch_add(rule, rp->nl_ctx->batch, nl_flags, + rp->nl_ctx->seqnum); + break; + case NFTNL_CMD_DELETE: + ret = mnl_nft_rule_batch_del(rule, rp->nl_ctx->batch, + 0, rp->nl_ctx->seqnum); + break; + case NFTNL_CMD_REPLACE: + nl_flags = NLM_F_REPLACE; + ret = mnl_nft_rule_batch_add(rule, rp->nl_ctx->batch, nl_flags, + rp->nl_ctx->seqnum); + break; + case NFTNL_CMD_INSERT: + nl_flags = NLM_F_CREATE; + nftnl_rule_unset(rule, NFTNL_RULE_HANDLE); + ret = mnl_nft_rule_batch_add(rule, rp->nl_ctx->batch, nl_flags, + rp->nl_ctx->seqnum); + break; + default: + errno = EOPNOTSUPP; + break; + } + + return ret; + +} + +static int netlink_markup_rule(const struct nftnl_parse_ctx *ctx) +{ + struct nftnl_rule *rule; + uint32_t cmd; + + cmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD); + rule = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_RULE); + + return netlink_markup_build_rule(ctx, cmd, rule); +} + +static int netlink_markup_build_flush(const struct nftnl_parse_ctx *ctx) +{ + struct nftnl_rule *rule; + struct nftnl_table *table; + struct nftnl_chain *chain; + const char *table_get_name, *table_get_family; + const char *chain_get_table, *chain_get_name, *chain_get_family; + uint32_t type; + int ret = -1; + + rule = nftnl_rule_alloc(); + if (rule == NULL) + return -1; + + type = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_TYPE); + switch (type) { + case NFTNL_RULESET_TABLE: + table = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_TABLE); + table_get_name = nftnl_table_get(table, NFTNL_TABLE_NAME); + table_get_family = nftnl_table_get(table, NFTNL_TABLE_FAMILY); + + nftnl_rule_set(rule, NFTNL_RULE_TABLE, table_get_name); + nftnl_rule_set(rule, NFTNL_RULE_FAMILY, table_get_family); + break; + case NFTNL_RULESET_CHAIN: + chain = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_CHAIN); + chain_get_table = nftnl_chain_get(chain, NFTNL_CHAIN_TABLE); + chain_get_name = nftnl_chain_get(chain, NFTNL_CHAIN_NAME); + chain_get_family = nftnl_chain_get(chain, NFTNL_TABLE_FAMILY); + + nftnl_rule_set(rule, NFTNL_RULE_TABLE, chain_get_table); + nftnl_rule_set(rule, NFTNL_RULE_CHAIN, chain_get_name); + nftnl_rule_set(rule, NFTNL_RULE_FAMILY, chain_get_family); + break; + default: + errno = EOPNOTSUPP; + goto err; + } + + ret = netlink_markup_build_rule(ctx, NFTNL_CMD_DELETE, rule); +err: + nftnl_rule_free(rule); + return ret; +} + +static int netlink_markup_chain(const struct nftnl_parse_ctx *ctx) +{ + const struct ruleset_parse *rp; + struct nftnl_chain *chain; + uint32_t cmd; + int ret = -1; + + chain = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_CHAIN); + rp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA); + + nftnl_chain_unset(chain, NFTNL_CHAIN_HANDLE); + + cmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD); + switch (cmd) { + case NFTNL_CMD_ADD: + ret = mnl_nft_chain_batch_add(chain, rp->nl_ctx->batch, + 0, rp->nl_ctx->seqnum); + break; + case NFTNL_CMD_DELETE: + ret = mnl_nft_chain_batch_del(chain, rp->nl_ctx->batch, + 0, rp->nl_ctx->seqnum); + break; + case NFTNL_CMD_FLUSH: + ret = netlink_markup_build_flush(ctx); + break; + default: + errno = EOPNOTSUPP; + break; + } + + return ret; +} + + +static int netlink_markup_build_table(const struct nftnl_parse_ctx *ctx, + uint32_t cmd, struct nftnl_table *table) +{ + struct ruleset_parse *rp; + int ret = -1; + + rp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA); + + switch (cmd) { + case NFTNL_CMD_ADD: + ret = mnl_nft_table_batch_add(table, rp->nl_ctx->batch, + 0, rp->nl_ctx->seqnum); + break; + case NFTNL_CMD_DELETE: + ret = mnl_nft_table_batch_del(table, rp->nl_ctx->batch, + 0, rp->nl_ctx->seqnum); + break; + case NFTNL_CMD_FLUSH: + ret = netlink_markup_build_flush(ctx); + break; + default: + errno = EOPNOTSUPP; + break; + } + + return ret; +} + +static int netlink_markup_table(const struct nftnl_parse_ctx *ctx) +{ + struct nftnl_table *table; + uint32_t cmd; + + cmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD); + table = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_TABLE); + + return netlink_markup_build_table(ctx, cmd, table); +} + +static int netlink_markup_flush(const struct nftnl_parse_ctx *ctx) +{ + struct nftnl_table *table; + int ret; + + table = nftnl_table_alloc(); + if (table == NULL) + return -1; + + ret = netlink_markup_build_table(ctx, NFTNL_CMD_DELETE, table); + nftnl_table_free(table); + + return ret; +} + +int netlink_markup_parse_cb(const struct nftnl_parse_ctx *ctx) +{ + struct ruleset_parse *rp; + uint32_t type; + int ret = -1; + + rp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA); + + type = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_TYPE); + switch (type) { + case NFTNL_RULESET_TABLE: + ret = netlink_markup_table(ctx); + break; + case NFTNL_RULESET_CHAIN: + ret = netlink_markup_chain(ctx); + break; + case NFTNL_RULESET_RULE: + ret = netlink_markup_rule(ctx); + break; + case NFTNL_RULESET_SET: + ret = netlink_markup_set(ctx); + break; + case NFTNL_RULESET_SET_ELEMS: + ret = netlink_markup_setelems(ctx); + break; + case NFTNL_RULESET_RULESET: + ret = netlink_markup_flush(ctx); + break; + default: + errno = EOPNOTSUPP; + break; + } + + nftnl_ruleset_ctx_free(ctx); + if (ret < 0) + netlink_io_error(rp->nl_ctx, &rp->cmd->location, + "Could not import: %s", strerror(errno)); + + return 0; +} + bool netlink_batch_supported(struct mnl_socket *nf_sock, uint32_t *seqnum) { return mnl_batch_supported(nf_sock, seqnum); diff --git a/src/parser_bison.y b/src/parser_bison.y index 6e85a62804d4..1c43a1809129 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -218,6 +218,7 @@ int nft_lex(void *, void *, void *); %token FLUSH "flush" %token RENAME "rename" %token DESCRIBE "describe" +%token IMPORT "import" %token EXPORT "export" %token MONITOR "monitor" @@ -473,6 +474,7 @@ int nft_lex(void *, void *, void *); %token XML "xml" %token JSON "json" +%token VM "vm" %token NOTRACK "notrack" @@ -492,8 +494,8 @@ int nft_lex(void *, void *, void *); %type line %destructor { cmd_free($$); } line -%type 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 -%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 +%type 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 +%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 %type table_spec chain_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec %destructor { handle_free(&$$); } table_spec chain_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec @@ -681,7 +683,7 @@ int nft_lex(void *, void *, void *); %destructor { expr_free($$); } fib_expr %type fib_tuple fib_result fib_flag -%type export_format +%type markup_format %type monitor_event %destructor { xfree($$); } monitor_event %type monitor_object monitor_format @@ -812,6 +814,7 @@ base_cmd : /* empty */ add_cmd { $$ = $1; } | RESET reset_cmd { $$ = $2; } | FLUSH flush_cmd { $$ = $2; } | RENAME rename_cmd { $$ = $2; } + | IMPORT import_cmd { $$ = $2; } | EXPORT export_cmd { $$ = $2; } | MONITOR monitor_cmd { $$ = $2; } | DESCRIBE describe_cmd { $$ = $2; } @@ -1181,18 +1184,34 @@ rename_cmd : CHAIN chain_spec identifier } ; -export_cmd : RULESET export_format +import_cmd : RULESET markup_format { struct handle h = { .family = NFPROTO_UNSPEC }; - struct export *export = export_alloc($2); - $$ = cmd_alloc(CMD_EXPORT, CMD_OBJ_EXPORT, &h, &@$, export); + struct markup *markup = markup_alloc($2); + $$ = cmd_alloc(CMD_IMPORT, CMD_OBJ_MARKUP, &h, &@$, markup); } - | export_format + | markup_format { struct handle h = { .family = NFPROTO_UNSPEC }; - struct export *export = export_alloc($1); - $$ = cmd_alloc(CMD_EXPORT, CMD_OBJ_EXPORT, &h, &@$, export); + struct markup *markup = markup_alloc($1); + $$ = cmd_alloc(CMD_IMPORT, CMD_OBJ_MARKUP, &h, &@$, markup); } + | JSON { $$ = NULL; } + ; + +export_cmd : RULESET markup_format + { + struct handle h = { .family = NFPROTO_UNSPEC }; + struct markup *markup = markup_alloc($2); + $$ = cmd_alloc(CMD_EXPORT, CMD_OBJ_MARKUP, &h, &@$, markup); + } + | markup_format + { + struct handle h = { .family = NFPROTO_UNSPEC }; + struct markup *markup = markup_alloc($1); + $$ = cmd_alloc(CMD_EXPORT, CMD_OBJ_MARKUP, &h, &@$, markup); + } + | JSON { $$ = NULL; } ; monitor_cmd : monitor_event monitor_object monitor_format @@ -1219,11 +1238,12 @@ monitor_object : /* empty */ { $$ = CMD_MONITOR_OBJ_ANY; } ; monitor_format : /* empty */ { $$ = NFTNL_OUTPUT_DEFAULT; } - | export_format + | markup_format + | JSON { $$ = NULL; } ; -export_format : XML { $$ = NFTNL_OUTPUT_XML; } - | JSON { $$ = NFTNL_OUTPUT_JSON; } +markup_format : XML { $$ = NFTNL_OUTPUT_XML; } + | VM JSON { $$ = NFTNL_OUTPUT_JSON; } ; describe_cmd : primary_expr diff --git a/src/rule.c b/src/rule.c index cbc40e2d101c..e7fa2909c8ef 100644 --- a/src/rule.c +++ b/src/rule.c @@ -898,19 +898,19 @@ void nft_cmd_expand(struct cmd *cmd) } } -struct export *export_alloc(uint32_t format) +struct markup *markup_alloc(uint32_t format) { - struct export *export; + struct markup *markup; - export = xmalloc(sizeof(struct export)); - export->format = format; + markup = xmalloc(sizeof(struct markup)); + markup->format = format; - return export; + return markup; } -void export_free(struct export *e) +void markup_free(struct markup *m) { - xfree(e); + xfree(m); } struct monitor *monitor_alloc(uint32_t format, uint32_t type, const char *event) @@ -958,8 +958,8 @@ void cmd_free(struct cmd *cmd) case CMD_OBJ_MONITOR: monitor_free(cmd->monitor); break; - case CMD_OBJ_EXPORT: - export_free(cmd->export); + case CMD_OBJ_MARKUP: + markup_free(cmd->markup); break; case CMD_OBJ_COUNTER: case CMD_OBJ_QUOTA: @@ -1159,13 +1159,37 @@ static int do_command_export(struct netlink_ctx *ctx, struct cmd *cmd) return -1; } while (rs == NULL); - nftnl_ruleset_fprintf(fp, rs, cmd->export->format, 0); + nftnl_ruleset_fprintf(stdout, rs, cmd->markup->format, + NFTNL_OF_EVENT_NEW); + nft_print(ctx->octx, "\n"); nftnl_ruleset_free(rs); return 0; } +static int do_command_import(struct netlink_ctx *ctx, struct cmd *cmd) +{ + int ret; + struct nftnl_parse_err *err; + struct ruleset_parse rp = { + .nl_ctx = ctx, + .cmd = cmd + }; + + err = nftnl_parse_err_alloc(); + if (err == NULL) + return -1; + + ret = nftnl_ruleset_parse_file_cb(cmd->markup->format, stdin, err, &rp, + netlink_markup_parse_cb); + if (ret < 0) + nftnl_parse_perror("unable to import: parsing failed", err); + + nftnl_parse_err_free(err); + return ret; +} + static int do_list_table(struct netlink_ctx *ctx, struct cmd *cmd, struct table *table) { @@ -1791,6 +1815,8 @@ int do_command(struct netlink_ctx *ctx, struct cmd *cmd) return do_command_flush(ctx, cmd); case CMD_RENAME: return do_command_rename(ctx, cmd); + case CMD_IMPORT: + return do_command_import(ctx, cmd); case CMD_EXPORT: return do_command_export(ctx, cmd); case CMD_MONITOR: diff --git a/src/scanner.l b/src/scanner.l index 6f19eec9c11b..5402be1cc2b0 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -274,6 +274,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "reset" { return RESET; } "flush" { return FLUSH; } "rename" { return RENAME; } +"import" { return IMPORT; } "export" { return EXPORT; } "monitor" { return MONITOR; } @@ -518,6 +519,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "xml" { return XML; } "json" { return JSON; } +"vm" { return VM; } "exists" { return EXISTS; } "missing" { return MISSING; } From patchwork Tue Dec 5 14:07:35 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shyam Saini X-Patchwork-Id: 844761 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Pjw1hyfq"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yrk9K392Rz9tB8 for ; Wed, 6 Dec 2017 01:08:05 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752690AbdLEOIC (ORCPT ); Tue, 5 Dec 2017 09:08:02 -0500 Received: from mail-pg0-f67.google.com ([74.125.83.67]:39348 "EHLO mail-pg0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753414AbdLEOH4 (ORCPT ); Tue, 5 Dec 2017 09:07:56 -0500 Received: by mail-pg0-f67.google.com with SMTP id w7so210496pgv.6 for ; Tue, 05 Dec 2017 06:07:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=XmX9v2U3UvXFwrHGwKJlRpXaRseczxp/mdijM0ctXls=; b=Pjw1hyfqoZ6hYHCc6c7xrNEtcwdzdkXimzzqm1Y7wW+UkjTzmZfwB68+VgaNZmaZXF vBCXGDAsUkGpUmu0Jk6aqJq4R/ebWWn58JjF8QmOBabJe+7z62eXFx3l8HOuGplJhy5U Le8PWkf0IEe6c3SIOBgKy2yfpq45dnDAyCGOHOx9qWIF/z+n5tKT7WrazW9peVwYH/DQ mrnWHvqbkbEG8No7W0YLdF64Q6qUJLz7C0eHO8/olY8yT+yIH2d+4B0/RDZWIZH8HQAS ZJqOumImjIUdJe+0iuh3cyzS2VwTO1GrfDh6jimY1IjalmQ6dFhFyWVilNMlPIpgqrve Zgzg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=XmX9v2U3UvXFwrHGwKJlRpXaRseczxp/mdijM0ctXls=; b=NIFSkFC85+cxYlP/Gwu8xM7DKSvUfT5DnICOI1wmI0nLpWECLkVTjKXuxZqkjc6wYu nHmasmFDrx2wyQSAt9fNyOLKMakbh0HK6YlPMQFL50BHzMfRu+n/fgQL8thRkKptVkaY D8aYcw5+o/Nt6ao17BR4k73WZ2EuHvws6koqB7gAY8Nxt71KV42QSc4Q3fJ+FLqRVpRa RkAcD1E8/Jm3OAd9uJf/O2fcTjd4F0pmuw+D3VYIxW0qmgxehm2F8NTx1+3ncwEOf/Zl woFzkgFkR0c/dAMlUfoMSudcKCcDk2mRW2ntJ+A874Cnjf1QsP15HTPah8IUmd4MZgAE d6KQ== X-Gm-Message-State: AJaThX6hrb2a/+vu+bxXtazb+ZPzIGLDJcdt0+B8jxFSwFr/w3dsm5cf 6HkmffZXaaUkFkX0g3n0vtms3w== X-Google-Smtp-Source: AGs4zMbxErT2CHkfQtqQZIZTVUyY2/796AhkbxcCSH01JsGhDSe4n5kfJdtudsG+4DWz6NsNlKfa+Q== X-Received: by 10.99.100.67 with SMTP id y64mr17523465pgb.19.1512482875369; Tue, 05 Dec 2017 06:07:55 -0800 (PST) Received: from administrator-ThinkPad-L450.one97.delhi.net ([203.122.38.200]) by smtp.gmail.com with ESMTPSA id b10sm520200pfj.20.2017.12.05.06.07.53 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 05 Dec 2017 06:07:54 -0800 (PST) From: Shyam Saini To: netfilter-devel@vger.kernel.org Cc: Shyam Saini Subject: [PATCH nft V5 2/2] tests: shell: Add tests for low level json import Date: Tue, 5 Dec 2017 19:37:35 +0530 Message-Id: <1512482855-29426-2-git-send-email-mayhs11saini@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1512482855-29426-1-git-send-email-mayhs11saini@gmail.com> References: <1512482855-29426-1-git-send-email-mayhs11saini@gmail.com> Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Test upcoming "import json" statement. Basically it loads same set of rules by "nft -f" and "nft import vm json" and prints differences(if any) in the ruleset listed by "nft list ruleset" in each case. For Example: $ ./run-tests.sh testcases/import/vm_json_import_0 Signed-off-by: Shyam Saini --- V5: Patch series rebased V4: Adopt new "vm" symbol for export/import operations --- tests/shell/testcases/import/vm_json_import_0 | 71 +++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100755 tests/shell/testcases/import/vm_json_import_0 diff --git a/tests/shell/testcases/import/vm_json_import_0 b/tests/shell/testcases/import/vm_json_import_0 new file mode 100755 index 000000000000..dc367f646140 --- /dev/null +++ b/tests/shell/testcases/import/vm_json_import_0 @@ -0,0 +1,71 @@ +#!/bin/bash + +tmpfile=$(mktemp) + +if [ ! -w $tmpfile ] ; then + echo "Failed to create tmp file" >&2 + exit 0 +fi + +trap "rm -rf $tmpfile" EXIT # cleanup if aborted + +RULESET="table ip mangle { + set blackhole { + type ipv4_addr + elements = { 192.168.1.4, 192.168.1.5 } + } + + chain prerouting { + type filter hook prerouting priority 0; policy accept; + tcp dport { ssh, http } accept + ip saddr @blackhole drop + icmp type echo-request accept + iifname \"lo\" accept + icmp type echo-request counter packets 0 bytes 0 + ct state established,related accept + tcp flags != syn counter packets 7 bytes 841 + ip saddr 192.168.1.100 ip daddr 192.168.1.1 counter packets 0 bytes 0 + } +} +table arp x { + chain y { + arp htype 22 + arp ptype ip + arp operation != rrequest + arp operation { request, reply, rrequest, rreply, inrequest, inreply, nak } + arp hlen 33-45 + } +} +table bridge x { + chain y { + type filter hook input priority 0; policy accept; + vlan id 4094 + vlan id 4094 vlan cfi 0 + vlan id 1 ip saddr 10.0.0.0/23 udp dport domain + } +} +table ip6 x { + chain y { + type nat hook postrouting priority 0; policy accept; + icmpv6 id 33-45 + ip6 daddr fe00::1-fe00::200 udp dport domain counter packets 0 bytes 0 + meta l4proto tcp masquerade to :1024 + iifname \"wlan0\" ct state established,new tcp dport vmap { ssh : drop, 222 : drop } masquerade + tcp dport ssh ip6 daddr 1::2 ether saddr 00:0f:54:0c:11:04 accept + ip6 daddr fe00::1-fe00::200 udp dport domain counter packets 0 bytes 0 masquerade + } +}" + +echo "$RULESET" > $tmpfile +$NFT -f $tmpfile +$NFT export vm json > $tmpfile +$NFT flush ruleset +cat $tmpfile | $NFT import vm json + +RESULT="$($NFT list ruleset)" + + +if [ "$RULESET" != "$RESULT" ] ; then + DIFF="$(which diff)" + [ -x $DIFF ] && $DIFF -u <(echo "$RULESET") <(echo "$RESULT") +fi