From patchwork Tue Jun 5 14:30:48 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Fabian X-Patchwork-Id: 925510 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; dmarc=none (p=none dis=none) header.from=bosson.cz Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=bosson.cz header.i=@bosson.cz header.b="DVEWHLID"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 410ZD65vGLz9s08 for ; Wed, 6 Jun 2018 00:38:14 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752187AbeFEOiK (ORCPT ); Tue, 5 Jun 2018 10:38:10 -0400 Received: from mailalternative.uvtmail.cz ([109.205.75.52]:44948 "EHLO mail.hosting.cldn.cz" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752487AbeFEOiF (ORCPT ); Tue, 5 Jun 2018 10:38:05 -0400 Received: from linux.local (linux.uvt.cz [178.17.1.67]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: fabian@bosson.cz) by mail.hosting.cldn.cz (Postfix) with ESMTPSA id 3B9F627D5E for ; Tue, 5 Jun 2018 16:31:24 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bosson.cz; s=mail; t=1528209084; bh=32SzepLncjD0VONlsZ6bX0QgHQiYAz7wWCjLBnfL16A=; h=From:To:Subject:Date:In-Reply-To:References; b=DVEWHLIDfQ6J9Z+OmwV5qiKTych4o1Ma19JH4A6HepQpdDSWrV9GBjiJoadGDDqtp WffnzT31rZLmspRmZg/hyGN9+jiJmXR5Tq4j29viUZlhLcP5+MkGe0+KkSxkGmktqv APlSbc2ZKBNOytPjKDFgzKJYqO5kUcm/4Q8lrSaydOoSwrviYKl65SnHHQ4TKmX9Mn sxW2J0WYeRuO6exZis8Chpgca5d6tXy50VvhqxS9FnuCg8l7Y53yuHjQVZxEukXdrF oncPkpmHG5OjSvMSiOjtm5YLMP5VAcXGmSBBb4fAgGLBGAQQrBumPZVGEqwIA28bKA ETwx8lK4n7l7g== From: David Fabian To: netfilter-devel@vger.kernel.org Subject: [PATCH v2 1/4] Added implicit variable scope to each include command to support local variables Date: Tue, 5 Jun 2018 16:30:48 +0200 Message-Id: <20180605143051.19274-2-david.fabian@bosson.cz> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180605143051.19274-1-david.fabian@bosson.cz> References: <20180605143051.19274-1-david.fabian@bosson.cz> Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org --- include/parser.h | 10 ++++++++-- src/libnftables.c | 2 ++ src/parser_bison.y | 14 ++++++++++---- src/rule.c | 1 + src/scanner.l | 18 +++++++++++++++++- 5 files changed, 38 insertions(+), 7 deletions(-) diff --git a/include/parser.h b/include/parser.h index ea41ca0..1f3eb5f 100644 --- a/include/parser.h +++ b/include/parser.h @@ -4,14 +4,14 @@ #include #include // FIXME -#define MAX_INCLUDE_DEPTH 16 +#define MAX_INCLUDE_DEPTH 64 #define TABSIZE 8 #define YYLTYPE struct location #define YYLTYPE_IS_TRIVIAL 0 #define YYENABLE_NLS 0 -#define SCOPE_NEST_MAX 3 +#define SCOPE_NEST_MAX (MAX_INCLUDE_DEPTH + 3) struct parser_state { struct input_descriptor *indesc; @@ -33,6 +33,12 @@ struct mnl_socket; extern void parser_init(struct nft_ctx *nft, struct parser_state *state, struct list_head *msgs, struct list_head *cmds); +extern void parser_destroy(struct parser_state *state); + +extern void open_scope(struct parser_state *state, struct scope *scope); +extern void close_scope(struct parser_state *state); +extern struct scope *current_scope(const struct parser_state *state); + extern int nft_parse(struct nft_ctx *ctx, void *, struct parser_state *state); extern void *scanner_init(struct parser_state *state); diff --git a/src/libnftables.c b/src/libnftables.c index 5bc7ba0..54ad614 100644 --- a/src/libnftables.c +++ b/src/libnftables.c @@ -411,6 +411,7 @@ static int nft_parse_bison_buffer(struct nft_ctx *nft, char *buf, size_t buflen, list_for_each_entry(cmd, cmds, list) nft_cmd_expand(cmd); + parser_destroy(nft->state); return 0; } @@ -433,6 +434,7 @@ static int nft_parse_bison_filename(struct nft_ctx *nft, const char *filename, list_for_each_entry(cmd, cmds, list) nft_cmd_expand(cmd); + parser_destroy(nft->state); return 0; } diff --git a/src/parser_bison.y b/src/parser_bison.y index d13eaa6..16a1f75 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -51,27 +51,33 @@ void parser_init(struct nft_ctx *nft, struct parser_state *state, state->ectx.octx = &nft->output; } +void parser_destroy(struct parser_state *state) +{ + scope_release(state->scopes[0]); +} + static void yyerror(struct location *loc, struct nft_ctx *nft, void *scanner, struct parser_state *state, const char *s) { erec_queue(error(loc, "%s", s), state->msgs); } -static struct scope *current_scope(const struct parser_state *state) +struct scope *current_scope(const struct parser_state *state) { return state->scopes[state->scope]; } -static void open_scope(struct parser_state *state, struct scope *scope) +void open_scope(struct parser_state *state, struct scope *scope) { assert(state->scope < array_size(state->scopes) - 1); scope_init(scope, current_scope(state)); state->scopes[++state->scope] = scope; } -static void close_scope(struct parser_state *state) +void close_scope(struct parser_state *state) { assert(state->scope > 0); + scope_release(state->scopes[state->scope]); state->scope--; } @@ -778,6 +784,7 @@ common_block : INCLUDE QUOTED_STRING stmt_separator erec_queue(error(&@2, "redefinition of symbol '%s'", $2), state->msgs); xfree($2); + expr_free($4); YYERROR; } @@ -840,7 +847,6 @@ line : common_block { $$ = NULL; } if (state->nerrs) YYABORT; $$ = NULL; - YYACCEPT; } ; diff --git a/src/rule.c b/src/rule.c index 3e8dea4..38529af 100644 --- a/src/rule.c +++ b/src/rule.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include diff --git a/src/scanner.l b/src/scanner.l index 6a861cf..e6e255d 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -629,7 +629,15 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) {comment} <> { - update_pos(yyget_extra(yyscanner), yylloc, 1); + struct parser_state *state = yyget_extra(yyscanner); + struct scope *scope = current_scope(state); + update_pos(state, yylloc, 1); + /* only close scope if file was included, skip buffer parsing + since it does not create new scope */ + if (state->indesc && state->indesc->name) { + close_scope(state); + xfree(scope); + } scanner_pop_buffer(yyscanner); if (YY_CURRENT_BUFFER == NULL) return TOKEN_EOF; @@ -644,6 +652,10 @@ static void scanner_pop_buffer(yyscan_t scanner) struct parser_state *state = yyget_extra(scanner); yypop_buffer_state(scanner); + if (state->indesc && state->indesc->name) { + xfree(state->indesc->name); + state->indesc->name = NULL; + } state->indesc = &state->indescs[--state->indesc_idx - 1]; } @@ -651,6 +663,7 @@ static struct error_record *scanner_push_file(void *scanner, const char *filenam FILE *f, const struct location *loc) { struct parser_state *state = yyget_extra(scanner); + struct scope *scope = NULL; YY_BUFFER_STATE b; if (state->indesc_idx == MAX_INCLUDE_DEPTH) { @@ -668,6 +681,9 @@ static struct error_record *scanner_push_file(void *scanner, const char *filenam state->indesc->type = INDESC_FILE; state->indesc->name = xstrdup(filename); init_pos(state); + scope = xzalloc(sizeof(*scope)); + init_list_head(&scope->symbols); + open_scope(state, scope); return NULL; } From patchwork Tue Jun 5 14:30:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Fabian X-Patchwork-Id: 925509 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; dmarc=none (p=none dis=none) header.from=bosson.cz Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=bosson.cz header.i=@bosson.cz header.b="OaV9NF5T"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 410ZD574DJz9s0W for ; Wed, 6 Jun 2018 00:38:13 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752485AbeFEOiK (ORCPT ); Tue, 5 Jun 2018 10:38:10 -0400 Received: from mailalternative.uvtmail.cz ([109.205.75.52]:36160 "EHLO mail.hosting.cldn.cz" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752486AbeFEOiF (ORCPT ); Tue, 5 Jun 2018 10:38:05 -0400 Received: from linux.local (linux.uvt.cz [178.17.1.67]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: fabian@bosson.cz) by mail.hosting.cldn.cz (Postfix) with ESMTPSA id CD61127D55 for ; Tue, 5 Jun 2018 16:31:24 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bosson.cz; s=mail; t=1528209085; bh=8JyRWgElBWf9fzb4K8OMxs14+STjhew6IawcZZa3eFY=; h=From:To:Subject:Date:In-Reply-To:References; b=OaV9NF5Te+VQj9Fbi2aNU4fXyPe4a3g8UKGPZepLwSNyTYXGRAWVNsb0Ue1+e4up8 7wZWjE27TmdSLFoPoyjybyF87SH22GtSWE1FfjJrOkfUkxrBMnDe+ZSCyrFAgGq7u0 jzqAdW5n3DQqOyS1VRnbiYxGyeHTRaDm2+q06lM+uRva99SBN3SpFbjjtMCdWQNgIc XUkacmhxsEAw+sv9TWVOHZT4gVCMxv5Zxrfqbd/p+FmhlRlXYaUXHLML7zGVipM8vj 08Q1dtt5QGO6Cohl1F/7DMnnSL06UD9pcjZru9aeTLj6acG+O1LLphqUsmiTpeiqv6 N301xf5pFtupg== From: David Fabian To: netfilter-devel@vger.kernel.org Subject: [PATCH v2 2/4] Added support for global variable definitions. Date: Tue, 5 Jun 2018 16:30:49 +0200 Message-Id: <20180605143051.19274-3-david.fabian@bosson.cz> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180605143051.19274-1-david.fabian@bosson.cz> References: <20180605143051.19274-1-david.fabian@bosson.cz> Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Global variables live only in the top-level scope and can be accessed from anywhere. They are unloaded at the end of parsing. Global definitions cannot contain local variables because those may get deleted when the local scope goes away and the subsequent use of the global would lead to a SIGSEGV. --- include/rule.h | 5 +- src/parser_bison.y | 335 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/rule.c | 15 ++- src/scanner.l | 1 + 4 files changed, 347 insertions(+), 9 deletions(-) mode change 100644 => 100755 src/parser_bison.y mode change 100644 => 100755 src/scanner.l diff --git a/include/rule.h b/include/rule.h index cfecf7f..8991025 100644 --- a/include/rule.h +++ b/include/rule.h @@ -109,8 +109,9 @@ extern void symbol_bind(struct scope *scope, const char *identifier, struct expr *expr); extern int symbol_unbind(const struct scope *scope, const char *identifier); extern struct symbol *symbol_lookup(const struct scope *scope, - const char *identifier); -struct symbol *symbol_get(const struct scope *scope, const char *identifier); + const char *identifier, int *global); +struct symbol *symbol_get(const struct scope *scope, const char *identifier, + int *global); enum table_flags { TABLE_F_DORMANT = (1 << 0), diff --git a/src/parser_bison.y b/src/parser_bison.y old mode 100644 new mode 100755 index 16a1f75..4500aac --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -62,6 +62,11 @@ static void yyerror(struct location *loc, struct nft_ctx *nft, void *scanner, erec_queue(error(loc, "%s", s), state->msgs); } +static struct scope *toplevel_scope(const struct parser_state *state) +{ + return state->scopes[0]; +} + struct scope *current_scope(const struct parser_state *state) { return state->scopes[state->scope]; @@ -192,6 +197,7 @@ int nft_lex(void *, void *, void *); %token DEFINE "define" %token REDEFINE "redefine" %token UNDEFINE "undefine" +%token GLOBAL "global" %token FIB "fib" @@ -739,6 +745,18 @@ int nft_lex(void *, void *, void *); %type ct_l4protoname ct_obj_type +%type global_list_rhs_expr global_rhs_expr global_variable_expr global_basic_rhs_expr global_primary_rhs_expr global_symbol_expr +%destructor { expr_free($$); } global_list_rhs_expr global_rhs_expr global_variable_expr global_basic_rhs_expr global_primary_rhs_expr global_symbol_expr + +%type global_set_lhs_expr global_set_rhs_expr global_shift_rhs_expr global_and_rhs_expr global_exclusive_or_rhs_expr global_inclusive_or_rhs_expr +%destructor { expr_free($$); } global_set_lhs_expr global_set_rhs_expr global_shift_rhs_expr global_and_rhs_expr global_exclusive_or_rhs_expr global_inclusive_or_rhs_expr + +%type global_concat_rhs_expr global_prefix_rhs_expr global_initializer_expr +%destructor { expr_free($$); } global_concat_rhs_expr global_prefix_rhs_expr global_initializer_expr + +%type global_range_rhs_expr global_set_list_expr global_set_list_member_expr global_set_elem_expr_alloc global_set_expr global_set_elem_expr global_multiton_rhs_expr +%destructor { expr_free($$); } global_range_rhs_expr global_set_list_expr global_set_list_member_expr global_set_elem_expr_alloc global_set_expr global_set_elem_expr global_multiton_rhs_expr + %% input : /* empty */ @@ -780,7 +798,7 @@ common_block : INCLUDE QUOTED_STRING stmt_separator { struct scope *scope = current_scope(state); - if (symbol_lookup(scope, $2) != NULL) { + if (symbol_lookup(scope, $2, NULL) != NULL) { erec_queue(error(&@2, "redefinition of symbol '%s'", $2), state->msgs); xfree($2); @@ -807,8 +825,43 @@ common_block : INCLUDE QUOTED_STRING stmt_separator state->msgs); YYERROR; } + xfree($2); } + | GLOBAL DEFINE identifier '=' global_initializer_expr stmt_separator + { + struct scope *scope = toplevel_scope(state); + + if (symbol_lookup(scope, $3, NULL) != NULL) { + erec_queue(error(&@2, "redefinition of global symbol '%s'", $3), + state->msgs); + xfree($3); + expr_free($5); + YYERROR; + } + + symbol_bind(scope, $3, $5); + xfree($3); + } + | GLOBAL REDEFINE identifier '=' global_initializer_expr stmt_separator + { + struct scope *scope = toplevel_scope(state); + + symbol_bind(scope, $3, $5); + xfree($3); + } + | GLOBAL UNDEFINE identifier stmt_separator + { + struct scope *scope = toplevel_scope(state); + + if (symbol_unbind(scope, $3) < 0) { + erec_queue(error(&@2, "undefined global symbol '%s'", $3), + state->msgs); + YYERROR; + } + + xfree($3); + } | error stmt_separator { if (++state->nerrs == nft->parser_max_errors) @@ -2823,8 +2876,9 @@ variable_expr : '$' identifier { struct scope *scope = current_scope(state); struct symbol *sym; + int global; - sym = symbol_get(scope, $2); + sym = symbol_get(scope, $2, &global); if (!sym) { erec_queue(error(&@2, "unknown identifier '%s'", $2), state->msgs); @@ -2832,7 +2886,13 @@ variable_expr : '$' identifier YYERROR; } - $$ = variable_expr_alloc(&@$, scope, sym); + if (global) + /* global variables can only access top-level scope + this prevents SIGSEGVs when the local scope in which + the global is used has been freed */ + $$ = variable_expr_alloc(&@$, toplevel_scope(state), sym); + else + $$ = variable_expr_alloc(&@$, scope, sym); xfree($2); } ; @@ -4093,4 +4153,273 @@ exthdr_key : HBH { $$ = IPPROTO_HOPOPTS; } | MH { $$ = IPPROTO_MH; } ; +global_initializer_expr : global_rhs_expr + | global_list_rhs_expr + ; + +global_list_rhs_expr : global_basic_rhs_expr COMMA global_basic_rhs_expr + { + $$ = list_expr_alloc(&@$); + compound_expr_add($$, $1); + compound_expr_add($$, $3); + } + | global_list_rhs_expr COMMA global_basic_rhs_expr + { + $1->location = @$; + compound_expr_add($1, $3); + $$ = $1; + } + ; + +global_rhs_expr : global_concat_rhs_expr { $$ = $1; } + | global_multiton_rhs_expr { $$ = $1; } + | global_set_expr { $$ = $1; } + ; + +global_variable_expr : '$' identifier + { + struct scope *scope = toplevel_scope(state); + struct symbol *sym; + + sym = symbol_get(scope, $2, NULL); + if (!sym) { + scope = current_scope(state); + if (symbol_lookup(scope, $2, NULL) != NULL) { + erec_queue(error(&@2, "local variable '%s' not allowed in global definition", $2), + state->msgs); + } else { + erec_queue(error(&@2, "unknown identifier '%s'", $2), + state->msgs); + } + xfree($2); + YYERROR; + } + $$ = variable_expr_alloc(&@$, scope, sym); + xfree($2); + } + ; + +global_symbol_expr : global_variable_expr + | string + { + $$ = symbol_expr_alloc(&@$, SYMBOL_VALUE, + toplevel_scope(state), + $1); + xfree($1); + } + | AT identifier + { + $$ = symbol_expr_alloc(&@$, SYMBOL_SET, + toplevel_scope(state), + $2); + xfree($2); + } + ; + +global_primary_rhs_expr : global_symbol_expr { $$ = $1; } + | integer_expr { $$ = $1; } + | boolean_expr { $$ = $1; } + | keyword_expr { $$ = $1; } + | TCP + { + uint8_t data = IPPROTO_TCP; + $$ = constant_expr_alloc(&@$, &inet_protocol_type, + BYTEORDER_HOST_ENDIAN, + sizeof(data) * BITS_PER_BYTE, &data); + } + | UDP + { + uint8_t data = IPPROTO_UDP; + $$ = constant_expr_alloc(&@$, &inet_protocol_type, + BYTEORDER_HOST_ENDIAN, + sizeof(data) * BITS_PER_BYTE, &data); + } + | UDPLITE + { + uint8_t data = IPPROTO_UDPLITE; + $$ = constant_expr_alloc(&@$, &inet_protocol_type, + BYTEORDER_HOST_ENDIAN, + sizeof(data) * BITS_PER_BYTE, &data); + } + | ESP + { + uint8_t data = IPPROTO_ESP; + $$ = constant_expr_alloc(&@$, &inet_protocol_type, + BYTEORDER_HOST_ENDIAN, + sizeof(data) * BITS_PER_BYTE, &data); + } + | AH + { + uint8_t data = IPPROTO_AH; + $$ = constant_expr_alloc(&@$, &inet_protocol_type, + BYTEORDER_HOST_ENDIAN, + sizeof(data) * BITS_PER_BYTE, &data); + } + | ICMP + { + uint8_t data = IPPROTO_ICMP; + $$ = constant_expr_alloc(&@$, &inet_protocol_type, + BYTEORDER_HOST_ENDIAN, + sizeof(data) * BITS_PER_BYTE, &data); + } + | ICMP6 + { + uint8_t data = IPPROTO_ICMPV6; + $$ = constant_expr_alloc(&@$, &inet_protocol_type, + BYTEORDER_HOST_ENDIAN, + sizeof(data) * BITS_PER_BYTE, &data); + } + | COMP + { + uint8_t data = IPPROTO_COMP; + $$ = constant_expr_alloc(&@$, &inet_protocol_type, + BYTEORDER_HOST_ENDIAN, + sizeof(data) * BITS_PER_BYTE, &data); + } + | DCCP + { + uint8_t data = IPPROTO_DCCP; + $$ = constant_expr_alloc(&@$, &inet_protocol_type, + BYTEORDER_HOST_ENDIAN, + sizeof(data) * BITS_PER_BYTE, &data); + } + | SCTP + { + uint8_t data = IPPROTO_SCTP; + $$ = constant_expr_alloc(&@$, &inet_protocol_type, + BYTEORDER_HOST_ENDIAN, + sizeof(data) * BITS_PER_BYTE, &data); + } + | REDIRECT + { + uint8_t data = ICMP_REDIRECT; + $$ = constant_expr_alloc(&@$, &icmp_type_type, + BYTEORDER_HOST_ENDIAN, + sizeof(data) * BITS_PER_BYTE, &data); + } + ; + +global_shift_rhs_expr : global_primary_rhs_expr + | global_shift_rhs_expr LSHIFT global_primary_rhs_expr + { + $$ = binop_expr_alloc(&@$, OP_LSHIFT, $1, $3); + } + | global_shift_rhs_expr RSHIFT global_primary_rhs_expr + { + $$ = binop_expr_alloc(&@$, OP_RSHIFT, $1, $3); + } + ; + +global_and_rhs_expr : global_shift_rhs_expr + | global_and_rhs_expr AMPERSAND global_shift_rhs_expr + { + $$ = binop_expr_alloc(&@$, OP_AND, $1, $3); + } + ; + +global_exclusive_or_rhs_expr : global_and_rhs_expr + | global_exclusive_or_rhs_expr CARET global_and_rhs_expr + { + $$ = binop_expr_alloc(&@$, OP_XOR, $1, $3); + } + ; + +global_inclusive_or_rhs_expr : global_exclusive_or_rhs_expr + | global_inclusive_or_rhs_expr '|' global_exclusive_or_rhs_expr + { + $$ = binop_expr_alloc(&@$, OP_OR, $1, $3); + } + ; + +global_basic_rhs_expr : global_inclusive_or_rhs_expr + ; + +global_concat_rhs_expr : global_basic_rhs_expr + | global_concat_rhs_expr DOT global_basic_rhs_expr + { + if ($$->ops->type != EXPR_CONCAT) { + $$ = concat_expr_alloc(&@$); + compound_expr_add($$, $1); + } else { + struct location rhs[] = { + [1] = @2, + [2] = @3, + }; + location_update(&$3->location, rhs, 2); + + $$ = $1; + $$->location = @$; + } + compound_expr_add($$, $3); + } + ; + +global_prefix_rhs_expr : global_basic_rhs_expr SLASH NUM + { + $$ = prefix_expr_alloc(&@$, $1, $3); + } + ; + +global_range_rhs_expr : global_basic_rhs_expr DASH global_basic_rhs_expr + { + $$ = range_expr_alloc(&@$, $1, $3); + } + ; + +global_multiton_rhs_expr : global_prefix_rhs_expr + | global_range_rhs_expr + | wildcard_expr + ; + +global_set_list_expr : global_set_list_member_expr + { + $$ = set_expr_alloc(&@$, NULL); + compound_expr_add($$, $1); + } + | global_set_list_expr COMMA global_set_list_member_expr + { + compound_expr_add($1, $3); + $$ = $1; + } + | global_set_list_expr COMMA opt_newline + ; + +global_set_list_member_expr : opt_newline global_set_expr opt_newline + { + $$ = $2; + } + | opt_newline global_set_elem_expr opt_newline + { + $$ = $2; + } + | opt_newline global_set_elem_expr COLON global_set_rhs_expr opt_newline + { + $$ = mapping_expr_alloc(&@$, $2, $4); + } + ; + +global_set_lhs_expr : global_concat_rhs_expr + | global_multiton_rhs_expr + ; + +global_set_rhs_expr : global_concat_rhs_expr + | verdict_expr + ; + +global_set_elem_expr : global_set_elem_expr_alloc + | global_set_elem_expr_alloc set_elem_options + ; + +global_set_elem_expr_alloc : global_set_lhs_expr + { + $$ = set_elem_expr_alloc(&@1, $1); + } + ; + +global_set_expr : '{' global_set_list_expr '}' + { + $2->location = @$; + $$ = $2; + } + ; %% diff --git a/src/rule.c b/src/rule.c index 38529af..d40ec50 100644 --- a/src/rule.c +++ b/src/rule.c @@ -526,11 +526,12 @@ void symbol_bind(struct scope *scope, const char *identifier, struct expr *expr) list_add(&sym->list, &scope->symbols); } -struct symbol *symbol_get(const struct scope *scope, const char *identifier) +struct symbol *symbol_get(const struct scope *scope, const char *identifier, + int *global) { struct symbol *sym; - sym = symbol_lookup(scope, identifier); + sym = symbol_lookup(scope, identifier, global); if (!sym) return NULL; @@ -566,14 +567,20 @@ int symbol_unbind(const struct scope *scope, const char *identifier) return 0; } -struct symbol *symbol_lookup(const struct scope *scope, const char *identifier) +struct symbol *symbol_lookup(const struct scope *scope, const char *identifier, + int *global) { struct symbol *sym; + if (global) + *global = 0; while (scope != NULL) { list_for_each_entry(sym, &scope->symbols, list) { - if (!strcmp(sym->identifier, identifier)) + if (!strcmp(sym->identifier, identifier)) { + if (global && scope->parent == NULL) + *global = 1; return sym; + } } scope = scope->parent; } diff --git a/src/scanner.l b/src/scanner.l old mode 100644 new mode 100755 index e6e255d..96bb307 --- a/src/scanner.l +++ b/src/scanner.l @@ -236,6 +236,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "define" { return DEFINE; } "redefine" { return REDEFINE; } "undefine" { return UNDEFINE; } +"global" { return GLOBAL; } "describe" { return DESCRIBE; } From patchwork Tue Jun 5 14:30:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Fabian X-Patchwork-Id: 925506 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; dmarc=none (p=none dis=none) header.from=bosson.cz Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=bosson.cz header.i=@bosson.cz header.b="F662laGB"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 410ZD16HLHz9s08 for ; Wed, 6 Jun 2018 00:38:09 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752522AbeFEOiH (ORCPT ); Tue, 5 Jun 2018 10:38:07 -0400 Received: from mailalternative.uvtmail.cz ([109.205.75.52]:50606 "EHLO mail.hosting.cldn.cz" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752485AbeFEOiF (ORCPT ); Tue, 5 Jun 2018 10:38:05 -0400 Received: from linux.local (linux.uvt.cz [178.17.1.67]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: fabian@bosson.cz) by mail.hosting.cldn.cz (Postfix) with ESMTPSA id 68B7227DBC for ; Tue, 5 Jun 2018 16:31:25 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bosson.cz; s=mail; t=1528209085; bh=F54jwZJVlZu/h7vNgeddIsZXiJqr+f065GBwy9tiXSQ=; h=From:To:Subject:Date:In-Reply-To:References; b=F662laGBnXFc/7J1XCchcFD4/BLfLUjOvZ8DtcCzTPrBeu2jx6NHQDktukaokrJYS VBbgZpvZE4woA+F4WARBuLsrpAigJ6KQIcqrUMOZ+SX+54OCG1dbTqfmO8h6LdJwA6 5a4O946hLYsRRReJ55ffFLh/5pkme3MbOQbTRl1orlmpCvuacDRCSF+6u2xVVAQPEA XOVZtOtQE51QwrAIUUfkMgrFaMDYZYeBXiXUXsqwTBBN3FtNUYCkFYT0QIHBI6Qk/1 hQ9pOhI1gbx1UJmFIu11ePdRSp6Rc9PPXfd3n7jgkt6luqQymVl84tpH3Nwv8Y8dcQ s5yJss3cYXrTw== From: David Fabian To: netfilter-devel@vger.kernel.org Subject: [PATCH v2 3/4] Refactoring of indesc hierarchy. Date: Tue, 5 Jun 2018 16:30:50 +0200 Message-Id: <20180605143051.19274-4-david.fabian@bosson.cz> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180605143051.19274-1-david.fabian@bosson.cz> References: <20180605143051.19274-1-david.fabian@bosson.cz> Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Indesc structure is now bound to scopes. Fixed issues with glob includes incorrectly increase the inclusion depth value. The entire scope tree gets cleaned up at the end of parsing now to properly support displaying of error messages. --- include/nftables.h | 10 +++-- include/parser.h | 15 +++---- include/rule.h | 15 +++++-- src/parser_bison.y | 64 ++++++++++++++++++++-------- src/rule.c | 56 +++++++++++++++++++++---- src/scanner.l | 120 +++++++++++++++++++++-------------------------------- 6 files changed, 164 insertions(+), 116 deletions(-) diff --git a/include/nftables.h b/include/nftables.h index 5e209b4..28d6043 100644 --- a/include/nftables.h +++ b/include/nftables.h @@ -118,13 +118,15 @@ struct input_descriptor { struct location location; enum input_descriptor_types type; const char *name; - const char *data; + union { + const char *data; + FILE *fp; + }; unsigned int lineno; unsigned int column; - off_t token_offset; - off_t line_offset; + off_t token_offset; + off_t line_offset; }; - void ct_label_table_init(void); void mark_table_init(void); void gmp_init(void); diff --git a/include/parser.h b/include/parser.h index 1f3eb5f..eabb2f4 100644 --- a/include/parser.h +++ b/include/parser.h @@ -4,26 +4,19 @@ #include #include // FIXME -#define MAX_INCLUDE_DEPTH 64 +#define MAX_INCLUDE_DEPTH 16 #define TABSIZE 8 #define YYLTYPE struct location #define YYLTYPE_IS_TRIVIAL 0 #define YYENABLE_NLS 0 -#define SCOPE_NEST_MAX (MAX_INCLUDE_DEPTH + 3) - struct parser_state { - struct input_descriptor *indesc; - struct input_descriptor indescs[MAX_INCLUDE_DEPTH]; - unsigned int indesc_idx; - struct list_head *msgs; unsigned int nerrs; - struct scope top_scope; - struct scope *scopes[SCOPE_NEST_MAX]; - unsigned int scope; + struct scope *top_scope; // top-level scope + struct scope *scope; // current scope struct list_head *cmds; struct eval_ctx ectx; @@ -37,7 +30,9 @@ extern void parser_destroy(struct parser_state *state); extern void open_scope(struct parser_state *state, struct scope *scope); extern void close_scope(struct parser_state *state); +extern struct scope *toplevel_scope(const struct parser_state *state); extern struct scope *current_scope(const struct parser_state *state); +extern struct input_descriptor* get_indesc(struct parser_state *state); extern int nft_parse(struct nft_ctx *ctx, void *, struct parser_state *state); diff --git a/include/rule.h b/include/rule.h index 8991025..c2ff692 100644 --- a/include/rule.h +++ b/include/rule.h @@ -82,12 +82,19 @@ extern void handle_free(struct handle *h); * @parent: pointer to parent scope * @symbols: symbols bound in the scope */ +struct input_descriptor; struct scope { - const struct scope *parent; + struct list_head list; + struct scope *parent; + struct list_head scopes; + struct input_descriptor *indesc; + int depth; struct list_head symbols; }; -extern struct scope *scope_init(struct scope *scope, const struct scope *parent); +extern struct input_descriptor* indesc_alloc(void); +extern struct scope *scope_alloc(struct scope *parent, + struct input_descriptor *parent_indesc); extern void scope_release(const struct scope *scope); /** @@ -137,7 +144,7 @@ struct table { struct list_head list; struct handle handle; struct location location; - struct scope scope; + struct scope *scope; struct list_head chains; struct list_head sets; struct list_head objs; @@ -190,7 +197,7 @@ struct chain { int policy; const char *type; const char *dev; - struct scope scope; + struct scope *scope; struct list_head rules; }; diff --git a/src/parser_bison.y b/src/parser_bison.y index 4500aac..9982c5b 100755 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -36,14 +36,23 @@ #include "parser_bison.h" +struct scope *toplevel_scope(const struct parser_state *state) +{ + return state->top_scope; +} + +struct scope *current_scope(const struct parser_state *state) +{ + return state->scope; +} + void parser_init(struct nft_ctx *nft, struct parser_state *state, struct list_head *msgs, struct list_head *cmds) { memset(state, 0, sizeof(*state)); - init_list_head(&state->top_scope.symbols); state->msgs = msgs; state->cmds = cmds; - state->scopes[0] = scope_init(&state->top_scope, NULL); + state->top_scope = state->scope = scope_alloc(NULL, NULL); state->ectx.cache = &nft->cache; state->ectx.msgs = msgs; state->ectx.nf_sock = nft->nf_sock; @@ -53,7 +62,7 @@ void parser_init(struct nft_ctx *nft, struct parser_state *state, void parser_destroy(struct parser_state *state) { - scope_release(state->scopes[0]); + scope_release(state->top_scope); } static void yyerror(struct location *loc, struct nft_ctx *nft, void *scanner, @@ -62,35 +71,50 @@ static void yyerror(struct location *loc, struct nft_ctx *nft, void *scanner, erec_queue(error(loc, "%s", s), state->msgs); } -static struct scope *toplevel_scope(const struct parser_state *state) +void open_scope(struct parser_state *state, struct scope *scope) { - return state->scopes[0]; + list_add_tail(&scope->list, &state->scope->scopes); + state->scope = scope; } -struct scope *current_scope(const struct parser_state *state) +void open_scope_glob(struct parser_state *state, struct scope *scope) { - return state->scopes[state->scope]; + /* add the scope to the head of the current scope level list */ + list_add(&scope->list, state->scope->list.prev); + state->scope = scope; } -void open_scope(struct parser_state *state, struct scope *scope) +void close_scope(struct parser_state *state) { - assert(state->scope < array_size(state->scopes) - 1); - scope_init(scope, current_scope(state)); - state->scopes[++state->scope] = scope; + struct scope *scope = state->scope; + assert(state->scope->parent != NULL); + + /* no additional globs, backtrack */ + if (list_is_last(&scope->list, &scope->parent->scopes)) + state->scope = scope->parent; + else + state->scope = list_entry(scope->list.next, struct scope, list); } -void close_scope(struct parser_state *state) + +struct input_descriptor* get_indesc(struct parser_state *state) { - assert(state->scope > 0); - scope_release(state->scopes[state->scope]); - state->scope--; + struct scope *scope = state->scope; + while (scope) { + if (scope->indesc) + return scope->indesc; + scope = scope->parent; + } + /* should never happen */ + assert(false); + return NULL; } static void location_init(void *scanner, struct parser_state *state, struct location *loc) { memset(loc, 0, sizeof(*loc)); - loc->indesc = state->indesc; + loc->indesc = get_indesc(state); } static void location_update(struct location *loc, struct location *rhs, int n) @@ -1407,8 +1431,10 @@ describe_cmd : primary_expr table_block_alloc : /* empty */ { + struct scope *scope = scope_alloc(current_scope(state), NULL); $$ = table_alloc(); - open_scope(state, &$$->scope); + $$->scope->parent = current_scope(state); + open_scope(state, scope); } ; @@ -1518,8 +1544,10 @@ table_block : /* empty */ { $$ = $-1; } chain_block_alloc : /* empty */ { + struct scope *scope = scope_alloc(current_scope(state), NULL); $$ = chain_alloc(NULL); - open_scope(state, &$$->scope); + $$->scope->parent = current_scope(state); + open_scope(state, scope); } ; diff --git a/src/rule.c b/src/rule.c index d40ec50..aff6992 100644 --- a/src/rule.c +++ b/src/rule.c @@ -495,15 +495,42 @@ struct rule *rule_lookup(const struct chain *chain, uint64_t handle) return NULL; } -struct scope *scope_init(struct scope *scope, const struct scope *parent) +struct input_descriptor* indesc_alloc(void) { + struct input_descriptor* indesc = xzalloc(sizeof(struct input_descriptor)); + return indesc; +} + +struct scope *scope_alloc(struct scope *parent, + struct input_descriptor *parent_indesc) +{ + struct scope *scope = xzalloc(sizeof(*scope)); + init_list_head(&scope->list); + init_list_head(&scope->symbols); + init_list_head(&scope->scopes); scope->parent = parent; + scope->indesc = parent_indesc; + if (parent != NULL) + scope->depth = parent->depth + 1; return scope; } -void scope_release(const struct scope *scope) +static void scope_indesc_release(const struct input_descriptor *indesc) +{ + if (indesc == NULL) + return; + xfree(indesc->name); + if (indesc->type == INDESC_FILE) { + fclose(indesc->fp); + } +} + +static void single_scope_release(const struct scope *scope) { struct symbol *sym, *next; + + if (scope == NULL) + return; list_for_each_entry_safe(sym, next, &scope->symbols, list) { assert(sym->refcnt == 1); @@ -512,6 +539,18 @@ void scope_release(const struct scope *scope) expr_free(sym->expr); xfree(sym); } + scope_indesc_release(scope->indesc); + xfree(scope->indesc); +} + +void scope_release(const struct scope *scope) +{ + struct scope *other_scope, *next; + list_for_each_entry_safe(other_scope, next, &scope->scopes, list) { + scope_release(other_scope); + } + single_scope_release(scope); + xfree(scope); } void symbol_bind(struct scope *scope, const char *identifier, struct expr *expr) @@ -635,10 +674,9 @@ struct chain *chain_alloc(const char *name) chain = xzalloc(sizeof(*chain)); chain->refcnt = 1; init_list_head(&chain->rules); - init_list_head(&chain->scope.symbols); + chain->scope = scope_alloc(NULL, NULL); if (name != NULL) - chain->handle.chain.name = xstrdup(name); - + chain->handle.chain.name = xstrdup(name); chain->policy = -1; return chain; } @@ -658,7 +696,8 @@ void chain_free(struct chain *chain) list_for_each_entry_safe(rule, next, &chain->rules, list) rule_free(rule); handle_free(&chain->handle); - scope_release(&chain->scope); + list_del(&chain->scope->list); + scope_release(chain->scope); xfree(chain->type); if (chain->dev != NULL) xfree(chain->dev); @@ -816,7 +855,7 @@ struct table *table_alloc(void) init_list_head(&table->sets); init_list_head(&table->objs); init_list_head(&table->flowtables); - init_list_head(&table->scope.symbols); + table->scope = scope_alloc(NULL, NULL); table->refcnt = 1; return table; @@ -837,7 +876,8 @@ void table_free(struct table *table) list_for_each_entry_safe(obj, nobj, &table->objs, list) obj_free(obj); handle_free(&table->handle); - scope_release(&table->scope); + list_del(&table->scope->list); + scope_release(table->scope); xfree(table); } diff --git a/src/scanner.l b/src/scanner.l index 96bb307..e190811 100755 --- a/src/scanner.l +++ b/src/scanner.l @@ -56,41 +56,43 @@ } \ } -static void scanner_pop_buffer(yyscan_t scanner); - - static void init_pos(struct parser_state *state) { - state->indesc->lineno = 1; - state->indesc->column = 1; - state->indesc->token_offset = 0; - state->indesc->line_offset = 0; + struct input_descriptor *indesc = get_indesc(state); +/* printf("initializing pos to %p, name %s\n", indesc, indesc->name); */ + indesc->lineno = 1; + indesc->column = 1; + indesc->token_offset = 0; + indesc->line_offset = 0; } static void update_pos(struct parser_state *state, struct location *loc, int len) { - loc->indesc = state->indesc; - loc->first_line = state->indesc->lineno; - loc->last_line = state->indesc->lineno; - loc->first_column = state->indesc->column; - loc->last_column = state->indesc->column + len - 1; - state->indesc->column += len; + struct input_descriptor *indesc = get_indesc(state); + loc->indesc = indesc; + loc->first_line = indesc->lineno; + loc->last_line = indesc->lineno; + loc->first_column = indesc->column; + loc->last_column = indesc->column + len - 1; + indesc->column += len; } static void update_offset(struct parser_state *state, struct location *loc, unsigned int len) { - state->indesc->token_offset += len; - loc->token_offset = state->indesc->token_offset; - loc->line_offset = state->indesc->line_offset; + struct input_descriptor *indesc = get_indesc(state); + indesc->token_offset += len; + loc->token_offset = indesc->token_offset; + loc->line_offset = indesc->line_offset; } static void reset_pos(struct parser_state *state, struct location *loc) { - state->indesc->line_offset = state->indesc->token_offset; - state->indesc->lineno += 1; - state->indesc->column = 1; + struct input_descriptor *indesc = get_indesc(state); + indesc->line_offset = indesc->token_offset; + indesc->lineno += 1; + indesc->column = 1; } #define YY_USER_ACTION { \ @@ -620,7 +622,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) unsigned int diff; diff = TABSIZE - strlen("\t"); - diff -= (state->indesc->column - + diff -= (get_indesc(state)->column - strlen("\t") - 1) % TABSIZE; update_pos(state, yylloc, diff); @@ -631,15 +633,9 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) <> { struct parser_state *state = yyget_extra(yyscanner); - struct scope *scope = current_scope(state); update_pos(state, yylloc, 1); - /* only close scope if file was included, skip buffer parsing - since it does not create new scope */ - if (state->indesc && state->indesc->name) { - close_scope(state); - xfree(scope); - } - scanner_pop_buffer(yyscanner); + close_scope(state); + yypop_buffer_state(yyscanner); if (YY_CURRENT_BUFFER == NULL) return TOKEN_EOF; } @@ -648,26 +644,15 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) %% -static void scanner_pop_buffer(yyscan_t scanner) -{ - struct parser_state *state = yyget_extra(scanner); - - yypop_buffer_state(scanner); - if (state->indesc && state->indesc->name) { - xfree(state->indesc->name); - state->indesc->name = NULL; - } - state->indesc = &state->indescs[--state->indesc_idx - 1]; -} - static struct error_record *scanner_push_file(void *scanner, const char *filename, - FILE *f, const struct location *loc) + FILE *f, const struct location *loc, struct scope *parent) { struct parser_state *state = yyget_extra(scanner); - struct scope *scope = NULL; + struct scope *scope = scope_alloc(parent, indesc_alloc()); YY_BUFFER_STATE b; - if (state->indesc_idx == MAX_INCLUDE_DEPTH) { + if (scope->depth == MAX_INCLUDE_DEPTH) { + scope_release(scope); fclose(f); return error(loc, "Include nested too deeply, max %u levels", MAX_INCLUDE_DEPTH); @@ -676,20 +661,21 @@ static struct error_record *scanner_push_file(void *scanner, const char *filenam b = yy_create_buffer(f, YY_BUF_SIZE, scanner); yypush_buffer_state(b, scanner); - state->indesc = &state->indescs[state->indesc_idx++]; if (loc != NULL) - state->indesc->location = *loc; - state->indesc->type = INDESC_FILE; - state->indesc->name = xstrdup(filename); + scope->indesc->location = *loc; + scope->indesc->type = INDESC_FILE; + scope->indesc->name = xstrdup(filename); + scope->indesc->fp = f; + if (current_scope(state)->parent == parent) + open_scope_glob(state, scope); + else + open_scope(state, scope); init_pos(state); - scope = xzalloc(sizeof(*scope)); - init_list_head(&scope->symbols); - open_scope(state, scope); return NULL; } static int include_file(void *scanner, const char *filename, - const struct location *loc) + const struct location *loc, struct scope *parent) { struct parser_state *state = yyget_extra(scanner); struct error_record *erec; @@ -702,7 +688,7 @@ static int include_file(void *scanner, const char *filename, goto err; } - erec = scanner_push_file(scanner, filename, f, loc); + erec = scanner_push_file(scanner, filename, f, loc, parent); if (erec != NULL) goto err; return 0; @@ -716,6 +702,7 @@ static int include_glob(void *scanner, const char *pattern, { struct parser_state *state = yyget_extra(scanner); struct error_record *erec = NULL; + struct scope *scope = current_scope(state); bool wildcard = false; glob_t glob_data; unsigned int i; @@ -775,7 +762,7 @@ static int include_glob(void *scanner, const char *pattern, if (len == 0 || path[len - 1] == '/') continue; - ret = include_file(scanner, path, loc); + ret = include_file(scanner, path, loc, scope); if (ret != 0) goto err; } @@ -812,7 +799,8 @@ err: int scanner_read_file(void *scanner, const char *filename, const struct location *loc) { - return include_file(scanner, filename, loc); + struct parser_state *state = yyget_extra(scanner); + return include_file(scanner, filename, loc, current_scope(state)); } static bool search_in_include_path(const char *filename) @@ -878,12 +866,14 @@ void scanner_push_buffer(void *scanner, const struct input_descriptor *indesc, const char *buffer) { struct parser_state *state = yyget_extra(scanner); + struct scope *scope = scope_alloc(current_scope(state), indesc_alloc()); YY_BUFFER_STATE b; - state->indesc = &state->indescs[state->indesc_idx++]; - memcpy(state->indesc, indesc, sizeof(*state->indesc)); - state->indesc->data = buffer; - state->indesc->name = NULL; + open_scope(state, scope); + scope->indesc->type = indesc->type; + scope->indesc->name = xstrdup(indesc->name); + scope->indesc->data = buffer; + scope->indesc->name = NULL; b = yy_scan_string(buffer, scanner); assert(b != NULL); @@ -894,8 +884,6 @@ void *scanner_init(struct parser_state *state) { yyscan_t scanner; - state->indesc = state->indescs; - yylex_init_extra(state, &scanner); yyset_out(NULL, scanner); @@ -904,17 +892,5 @@ void *scanner_init(struct parser_state *state) void scanner_destroy(void *scanner) { - struct parser_state *state = yyget_extra(scanner); - - do { - struct input_descriptor *inpdesc = - &state->indescs[state->indesc_idx]; - if (inpdesc && inpdesc->name) { - xfree(inpdesc->name); - inpdesc->name = NULL; - } - yypop_buffer_state(scanner); - } while (state->indesc_idx--); - yylex_destroy(scanner); } From patchwork Tue Jun 5 14:30:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Fabian X-Patchwork-Id: 925508 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; dmarc=none (p=none dis=none) header.from=bosson.cz Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=bosson.cz header.i=@bosson.cz header.b="YvJKfgB0"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 410ZD52K5cz9s08 for ; Wed, 6 Jun 2018 00:38:13 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752005AbeFEOiJ (ORCPT ); Tue, 5 Jun 2018 10:38:09 -0400 Received: from mailalternative.uvtmail.cz ([109.205.75.52]:47028 "EHLO mail.hosting.cldn.cz" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752489AbeFEOiF (ORCPT ); Tue, 5 Jun 2018 10:38:05 -0400 Received: from linux.local (linux.uvt.cz [178.17.1.67]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: fabian@bosson.cz) by mail.hosting.cldn.cz (Postfix) with ESMTPSA id 0711E27DCB for ; Tue, 5 Jun 2018 16:31:26 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bosson.cz; s=mail; t=1528209086; bh=DNknIzzdlgY2Vt6EPtvCFy+HMbbXPl8VlRgE/gak9oE=; h=From:To:Subject:Date:In-Reply-To:References; b=YvJKfgB0DAVfE1HqLLk1VPPaxCFok+zNdRWfFGYxIS6icEs43M6GuANJsoLvn13SF 2YUTElJWbHr8pISqxrgFh+cp9cJC2C/WFksEgV9EOuKAdxalC/SEJ2kBTBG075xMHV DqT36z0cVjb0kZYv4x6Xk0p6MzkukMT/AeBxTAKt/ruDmsWxO/89z14yoUfQ5rEEbu Im48rcfJJ2eX3racdMavQKU8zpT67osamiXxrb0K/pcGEEDNi5m/dsafeaqaKbumfK jvniSuuAXy4R3z09z0orIMa6p2A6sC2USPCprISAc4aYo1CPltjx6Mmr5cIQhRuPW0 QkRhghJSlp4dQ== From: David Fabian To: netfilter-devel@vger.kernel.org Subject: [PATCH v2 4/4] Added tests for nested file-based scopes Date: Tue, 5 Jun 2018 16:30:51 +0200 Message-Id: <20180605143051.19274-5-david.fabian@bosson.cz> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180605143051.19274-1-david.fabian@bosson.cz> References: <20180605143051.19274-1-david.fabian@bosson.cz> Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org --- tests/shell/testcases/include/0016sibling_scopes_0 | 33 ++++++++++++++++++ .../shell/testcases/include/0017scope_hierarchy_0 | 39 ++++++++++++++++++++++ tests/shell/testcases/include/0018global_define_0 | 38 +++++++++++++++++++++ tests/shell/testcases/include/0019global_define_1 | 20 +++++++++++ .../include/dumps/0016sibling_scopes_0.nft | 0 .../include/dumps/0017scope_hierarchy_0.nft | 0 .../include/dumps/0018global_define_0.nft | 0 7 files changed, 130 insertions(+) create mode 100755 tests/shell/testcases/include/0016sibling_scopes_0 create mode 100755 tests/shell/testcases/include/0017scope_hierarchy_0 create mode 100755 tests/shell/testcases/include/0018global_define_0 create mode 100755 tests/shell/testcases/include/0019global_define_1 create mode 100644 tests/shell/testcases/include/dumps/0016sibling_scopes_0.nft create mode 100644 tests/shell/testcases/include/dumps/0017scope_hierarchy_0.nft create mode 100644 tests/shell/testcases/include/dumps/0018global_define_0.nft diff --git a/tests/shell/testcases/include/dumps/0016sibling_scopes_0.nft b/tests/shell/testcases/include/dumps/0016sibling_scopes_0.nft new file mode 100644 index 0000000..e69de29 diff --git a/tests/shell/testcases/include/dumps/0017scope_hierarchy_0.nft b/tests/shell/testcases/include/dumps/0017scope_hierarchy_0.nft new file mode 100644 index 0000000..e69de29 diff --git a/tests/shell/testcases/include/dumps/0018global_define_0.nft b/tests/shell/testcases/include/dumps/0018global_define_0.nft new file mode 100644 index 0000000..e69de29 diff --git a/tests/shell/testcases/include/0016sibling_scopes_0 b/tests/shell/testcases/include/0016sibling_scopes_0 new file mode 100755 index 0000000..c8b4d7f --- /dev/null +++ b/tests/shell/testcases/include/0016sibling_scopes_0 @@ -0,0 +1,33 @@ +#!/bin/bash + +set -e + +tmpdir=$(mktemp -d) +if [ ! -d $tmpdir ] ; then + echo "Failed to create tmp directory" >&2 + exit 0 +fi + +# cleanup if aborted +trap "rm -rf $tmpdir" EXIT + +cat > $tmpdir/top.nft << EOF +include "$tmpdir/a.nft" +include "$tmpdir/b.nft" + +EOF + +cat > $tmpdir/a.nft << EOF +define AAA = "testa" +EOF + +cat > $tmpdir/b.nft << EOF +define AAA = "testb" +EOF + +$NFT -f $tmpdir/top.nft + +if [ $? -ne 0 ] ; then + echo "E: unable to load good ruleset" >&2 + exit 1 +fi \ No newline at end of file diff --git a/tests/shell/testcases/include/0017scope_hierarchy_0 b/tests/shell/testcases/include/0017scope_hierarchy_0 new file mode 100755 index 0000000..ba99a58 --- /dev/null +++ b/tests/shell/testcases/include/0017scope_hierarchy_0 @@ -0,0 +1,39 @@ +#!/bin/bash + +set -e + +tmpdir=$(mktemp -d) +if [ ! -d $tmpdir ] ; then + echo "Failed to create tmp directory" >&2 + exit 0 +fi + +# cleanup if aborted +trap "rm -rf $tmpdir" EXIT + +cat > $tmpdir/top.nft << EOF +define TOP = "top" +include "$tmpdir/a.nft" +EOF + +cat > $tmpdir/a.nft << EOF +define AAA = "testa" +include "$tmpdir/sub/*.nft" +EOF + +mkdir $tmpdir/sub &> /dev/null + +cat > $tmpdir/sub/b.nft << EOF +define FOO = { \$TOP, abc } +EOF + +cat > $tmpdir/sub/c.nft << EOF +define BAR = { \$AAA, cdef } +EOF + +$NFT -f $tmpdir/top.nft + +if [ $? -ne 0 ] ; then + echo "E: unable to load good ruleset" >&2 + exit 1 +fi \ No newline at end of file diff --git a/tests/shell/testcases/include/0018global_define_0 b/tests/shell/testcases/include/0018global_define_0 new file mode 100755 index 0000000..4288862 --- /dev/null +++ b/tests/shell/testcases/include/0018global_define_0 @@ -0,0 +1,38 @@ +#!/bin/bash + +set -e + +tmpdir=$(mktemp -d) +if [ ! -d $tmpdir ] ; then + echo "Failed to create tmp directory" >&2 + exit 0 +fi + +# cleanup if aborted +trap "rm -rf $tmpdir" EXIT + +cat > $tmpdir/top.nft << EOF +define TOP = "top" +include "$tmpdir/a.nft" +define CCC = \$BBB +global undefine BBB +EOF + +cat > $tmpdir/a.nft << EOF +define AAA = "testa" +include "$tmpdir/sub/b.nft" +EOF + +mkdir $tmpdir/sub &> /dev/null + +cat > $tmpdir/sub/b.nft << EOF +global define BBB = "global" +global redefine BBB = "global2" +EOF + +$NFT -f $tmpdir/top.nft + +if [ $? -ne 0 ] ; then + echo "E: unable to load good ruleset" >&2 + exit 1 +fi diff --git a/tests/shell/testcases/include/0019global_define_1 b/tests/shell/testcases/include/0019global_define_1 new file mode 100755 index 0000000..11d9dd2 --- /dev/null +++ b/tests/shell/testcases/include/0019global_define_1 @@ -0,0 +1,20 @@ +#!/bin/bash + +set -e + +tmpdir=$(mktemp -d) +if [ ! -d $tmpdir ] ; then + echo "Failed to create tmp directory" >&2 + exit 0 +fi + +# cleanup if aborted +trap "rm -rf $tmpdir" EXIT + +cat > $tmpdir/top.nft << EOF +define TOP = "top" +global define FAIL = \$TOP +EOF + +$NFT -f $tmpdir/top.nft 2> /dev/null +echo "E: local variable in global define"