From 998f010120cf91578717d3ed037bad16f80c963f Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 16 Jan 2014 18:12:06 +0000 Subject: build: fix recursive parser.h inclusion Ocassionally when regenerating the scanner or parser (not sure which), recursive inclusion of the parser.h file occurs. The reason is that bison doesn't generate a header sandwich to protect against this (*sigh*). Change the makefile to do this manually. Signed-off-by: Patrick McHardy --- Makefile.rules.in | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Makefile.rules.in b/Makefile.rules.in index 25988dd7..ae563a54 100644 --- a/Makefile.rules.in +++ b/Makefile.rules.in @@ -22,7 +22,14 @@ configure: configure.ac %.c %.h: %.y $(makedeps) @echo -e " YACC\t\t$<" - $(YACC) $(YACCFLAGS) -d -o $@ $< + $(YACC) $(YACCFLAGS) --defines=$*.h.tmp -o $@ $< + ( \ + echo "#ifndef __$(*F)_H"; \ + echo "#define __$(*F)_H"; \ + cat $*.h.tmp; \ + echo "#endif /* __$(*F)_H */" \ + ) > $*.h + $(RM) $*.h.tmp %.c %.h: %.l $(makedeps) @echo -e " LEX\t\t$<" -- cgit v1.2.3 From a4b1c0c704d082a70fe68b3a97a9c03416f63ccf Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 16 Jan 2014 17:42:02 +0100 Subject: src: add new --debug=mnl option to enable libmnl debugging This allows you to dump the netlink message that is send via libmnl. Signed-off-by: Pablo Neira Ayuso --- include/nftables.h | 1 + src/main.c | 6 +++++- src/mnl.c | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/include/nftables.h b/include/nftables.h index f9891619..b36e10ae 100644 --- a/include/nftables.h +++ b/include/nftables.h @@ -18,6 +18,7 @@ enum debug_level { DEBUG_EVALUATION = 0x4, DEBUG_NETLINK = 0x8, DEBUG_SEGTREE = 0x10, + DEBUG_MNL = 0x20, }; #define INCLUDE_PATHS_MAX 16 diff --git a/src/main.c b/src/main.c index d78eea79..3f5dd04e 100644 --- a/src/main.c +++ b/src/main.c @@ -111,7 +111,7 @@ static void show_help(const char *name) " -a/--handle Output rule handle.\n" " -I/--includepath Add to the paths searched for include files.\n" #ifdef DEBUG -" --debug Specify debugging level (scanner, parser, eval, netlink, segtree, all)\n" +" --debug Specify debugging level (scanner, parser, eval, netlink, mnl, segtree, all)\n" #endif "\n", name); @@ -138,6 +138,10 @@ static const struct { .name = "netlink", .level = DEBUG_NETLINK, }, + { + .name = "mnl", + .level = DEBUG_MNL, + }, { .name = "segtree", .level = DEBUG_SEGTREE, diff --git a/src/mnl.c b/src/mnl.c index a4a4c4af..16625000 100644 --- a/src/mnl.c +++ b/src/mnl.c @@ -39,7 +39,7 @@ mnl_talk(struct mnl_socket *nf_sock, const void *data, unsigned int len, int ret; #ifdef DEBUG - if (debug_level & DEBUG_NETLINK) + if (debug_level & DEBUG_MNL) mnl_nlmsg_fprintf(stdout, data, len, sizeof(struct nfgenmsg)); #endif @@ -207,7 +207,7 @@ static ssize_t mnl_nft_socket_sendmsg(const struct mnl_socket *nl) iov[i].iov_len = mnl_nlmsg_batch_size(batch_page->batch); i++; #ifdef DEBUG - if (debug_level & DEBUG_NETLINK) { + if (debug_level & DEBUG_MNL) { mnl_nlmsg_fprintf(stdout, mnl_nlmsg_batch_head(batch_page->batch), mnl_nlmsg_batch_size(batch_page->batch), -- cgit v1.2.3 From 21cfa9a7405f78f424c869e592d21ebdaf379803 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 16 Jan 2014 18:31:16 +0100 Subject: src: use ':' instead of '=>' in dictionaries Replace => by : to make it easier for most shell users, as > implies a redirection, let's avoid possible confusion that may result if you forget to escape it. This works fine if you don't forget to add space between the key and the value. If you forget to add the space, depending on the case, the scanner may recognize it correctly or process it as a string. Signed-off-by: Pablo Neira Ayuso --- files/examples/sets_and_maps | 8 ++++---- include/expression.h | 2 +- src/expression.c | 2 +- src/parser.y | 7 +++---- src/rule.c | 2 +- src/scanner.l | 1 - tests/dictionary | 30 +++++++++++++++--------------- tests/loop-detect.3 | 2 +- tests/loop-detect.4 | 2 +- tests/verdict-maps | 6 +++--- 10 files changed, 30 insertions(+), 32 deletions(-) diff --git a/files/examples/sets_and_maps b/files/examples/sets_and_maps index adfc6884..a05199ae 100755 --- a/files/examples/sets_and_maps +++ b/files/examples/sets_and_maps @@ -25,13 +25,13 @@ table filter { type ifindex } - # named map of type ifindex => ipv4_address + # named map of type ifindex : ipv4_address map nat_map { - type ifindex => ipv4_address + type ifindex : ipv4_address } map jump_map { - type ifindex => verdict + type ifindex : verdict } chain input_1 { counter; } @@ -48,6 +48,6 @@ table filter { meta iif @local_ifs counter meta iif vmap @jump_map - #meta iif vmap { eth0 => jump input1, eth1 => jump input2 } + #meta iif vmap { eth0 : jump input1, eth1 : jump input2 } } } diff --git a/include/expression.h b/include/expression.h index f0eb7993..a167cf59 100644 --- a/include/expression.h +++ b/include/expression.h @@ -27,7 +27,7 @@ * @EXPR_LIST: list of expressions * @EXPR_SET: literal set * @EXPR_SET_REF: set reference - * @EXPR_MAPPING: a single mapping (key => value) + * @EXPR_MAPPING: a single mapping (key : value) * @EXPR_MAP: map operation (expr map { EXPR_MAPPING, ... }) * @EXPR_UNARY: byteorder conversion, generated during evaluation * @EXPR_BINOP: binary operations (bitwise, shifts) diff --git a/src/expression.c b/src/expression.c index a12133c8..c8566224 100644 --- a/src/expression.c +++ b/src/expression.c @@ -644,7 +644,7 @@ struct expr *set_expr_alloc(const struct location *loc) static void mapping_expr_print(const struct expr *expr) { expr_print(expr->left); - printf(" => "); + printf(" : "); expr_print(expr->right); } diff --git a/src/parser.y b/src/parser.y index d4a79291..5cd8ef67 100644 --- a/src/parser.y +++ b/src/parser.y @@ -150,7 +150,6 @@ static void location_update(struct location *loc, struct location *rhs, int n) %token ASTERISK "*" %token DASH "-" %token AT "@" -%token ARROW "=>" %token VMAP "vmap" %token INCLUDE "include" @@ -751,7 +750,7 @@ map_block : /* empty */ { $$ = $-1; } | map_block common_block | map_block stmt_seperator | map_block TYPE - identifier ARROW identifier + identifier COLON identifier stmt_seperator { $1->keytype = datatype_lookup_byname($3); @@ -1243,11 +1242,11 @@ set_list_member_expr : opt_newline expr opt_newline { $$ = $2; } - | opt_newline map_lhs_expr ARROW concat_expr opt_newline + | opt_newline map_lhs_expr COLON concat_expr opt_newline { $$ = mapping_expr_alloc(&@$, $2, $4); } - | opt_newline map_lhs_expr ARROW verdict_expr opt_newline + | opt_newline map_lhs_expr COLON verdict_expr opt_newline { $$ = mapping_expr_alloc(&@$, $2, $4); } diff --git a/src/rule.c b/src/rule.c index ec8b6a48..04dd6c77 100644 --- a/src/rule.c +++ b/src/rule.c @@ -96,7 +96,7 @@ void set_print(const struct set *set) printf("\t\ttype %s", set->keytype->name); if (set->flags & SET_F_MAP) - printf(" => %s", set->datatype->name); + printf(" : %s", set->datatype->name); printf("\n"); if (set->flags & SET_F_ANONYMOUS) diff --git a/src/scanner.l b/src/scanner.l index 936c035e..25fbc610 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -221,7 +221,6 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "@" { return AT; } "$" { return '$'; } "=" { return '='; } -"=>" { return ARROW; } "vmap" { return VMAP; } "include" { return INCLUDE; } diff --git a/tests/dictionary b/tests/dictionary index 41935295..b4e6c521 100644 --- a/tests/dictionary +++ b/tests/dictionary @@ -21,32 +21,32 @@ add rule ip filter OUTPUT tcp dport { \ 192.168.0.1, \ } -# must succeed: expr { expr => verdict, ... } +# must succeed: expr { expr : verdict, ... } add rule ip filter OUTPUT tcp dport vmap { \ - 22 => jump chain1, \ - 23 => jump chain2, \ + 22 : jump chain1, \ + 23 : jump chain2, \ } -# must fail: expr { expr => verdict, expr => expr, ... } +# must fail: expr { expr : verdict, expr : expr, ... } add rule ip filter OUTPUT tcp dport vmap { \ - 22 => jump chain1, \ - 23 => 0x100, \ + 22 : jump chain1, \ + 23 : 0x100, \ } -# must fail: expr { expr => expr, ...} +# must fail: expr { expr : expr, ...} add rule ip filter OUTPUT tcp dport vmap { \ - 22 => 0x100, \ - 23 => 0x200, \ + 22 : 0x100, \ + 23 : 0x200, \ } -# must succeed: expr MAP { expr => expr, ... } expr +# must succeed: expr MAP { expr : expr, ... } expr add rule ip filter OUTPUT meta mark set tcp dport map { \ - 22 => 1, \ - 23 => 2, \ + 22 : 1, \ + 23 : 2, \ } -# must fail: expr MAP { expr => type1, expr => type2, .. } expr +# must fail: expr MAP { expr : type1, expr : type2, .. } expr add rule ip filter OUTPUT meta mark set tcp dport map { \ - 22 => 1, \ - 23 => 192.168.0.1, \ + 22 : 1, \ + 23 : 192.168.0.1, \ } diff --git a/tests/loop-detect.3 b/tests/loop-detect.3 index 3b83ef12..80f7fc5a 100644 --- a/tests/loop-detect.3 +++ b/tests/loop-detect.3 @@ -4,4 +4,4 @@ flush table filter add filter chain1 jump chain2 add filter chain2 jump chain3 -add filter chain3 ip daddr vmap { 10.0.0.1 => continue, 192.168.0.1 => jump chain1 } +add filter chain3 ip daddr vmap { 10.0.0.1 : continue, 192.168.0.1 : jump chain1 } diff --git a/tests/loop-detect.4 b/tests/loop-detect.4 index f6f4d572..acd9a342 100644 --- a/tests/loop-detect.4 +++ b/tests/loop-detect.4 @@ -3,5 +3,5 @@ # Circular jump with an intermediate anonymous verdict map: chain1 -> chain2 -> chain3 -> chain1 flush table filter add filter chain1 jump chain2 -add filter chain2 ip daddr vmap { 10.0.0.1 => continue, 192.168.0.1 => jump chain3 } +add filter chain2 ip daddr vmap { 10.0.0.1 : continue, 192.168.0.1 : jump chain3 } add filter chain3 jump chain1 diff --git a/tests/verdict-maps b/tests/verdict-maps index 72ef98f9..c1630ce3 100644 --- a/tests/verdict-maps +++ b/tests/verdict-maps @@ -14,7 +14,7 @@ add chain ip filter chain3 add filter chain3 counter add filter input ip saddr vmap { \ - 10.0.0.0/24 => jump chain1, \ - 10.0.0.0/8 => jump chain2, \ - 8.8.8.8 => jump chain3 \ + 10.0.0.0/24 : jump chain1, \ + 10.0.0.0/8 : jump chain2, \ + 8.8.8.8 : jump chain3 \ } -- cgit v1.2.3 From 11884cfb1c0432cc455ff8e3269500e819e0c434 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 16 Jan 2014 20:01:56 +0000 Subject: set: make set flags output parsable This patch fixes two problems: - the output of "nft list table ..." is not parsable if sets are included because the parser can't parse the flags. - set flags can't be specified during set creation. To fix this, the set output is changed to: - not print each flag on a single line - prefix the flags with "flags " - only show the interval flag since all others are for internal use only The parser is changed to parse the flags specified in a set declaration. This allows to parse empty sets. The following patch will take care of parsing sets that are already populated. Signed-off-by: Patrick McHardy --- src/parser.y | 24 ++++++++++++++++++++++++ src/rule.c | 15 +++++++++------ src/scanner.l | 2 ++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/parser.y b/src/parser.y index 5cd8ef67..1b09e616 100644 --- a/src/parser.y +++ b/src/parser.y @@ -182,6 +182,8 @@ static void location_update(struct location *loc, struct location *rhs, int n) %token RETURN "return" %token QUEUE "queue" +%token INTERVAL "interval" + %token NUM "number" %token STRING "string" %token QUOTED_STRING @@ -353,6 +355,8 @@ static void location_update(struct location *loc, struct location *rhs, int n) %type rule %destructor { rule_free($$); } rule +%type set_flag_list set_flag + %type set_block_alloc set_block %destructor { set_free($$); } set_block_alloc @@ -737,6 +741,21 @@ set_block : /* empty */ { $$ = $-1; } } $$ = $1; } + | set_block FLAGS set_flag_list stmt_seperator + { + $1->flags = $3; + $$ = $1; + } + ; + +set_flag_list : set_flag_list COMMA set_flag + { + $$ = $1 | $3; + } + | set_flag + ; + +set_flag : INTERVAL { $$ = SET_F_INTERVAL; } ; map_block_alloc : /* empty */ @@ -769,6 +788,11 @@ map_block : /* empty */ { $$ = $-1; } $$ = $1; } + | map_block FLAGS set_flag_list stmt_seperator + { + $1->flags = $3; + $$ = $1; + } ; hook_spec : TYPE STRING HOOK STRING PRIORITY NUM diff --git a/src/rule.c b/src/rule.c index 04dd6c77..0f7f4b51 100644 --- a/src/rule.c +++ b/src/rule.c @@ -89,6 +89,7 @@ struct set *set_lookup(const struct table *table, const char *name) void set_print(const struct set *set) { + const char *delim = ""; const char *type; type = set->flags & SET_F_MAP ? "map" : "set"; @@ -99,12 +100,14 @@ void set_print(const struct set *set) printf(" : %s", set->datatype->name); printf("\n"); - if (set->flags & SET_F_ANONYMOUS) - printf("\t\tanonymous\n"); - if (set->flags & SET_F_CONSTANT) - printf("\t\tconstant\n"); - if (set->flags & SET_F_INTERVAL) - printf("\t\tinterval\n"); + if (set->flags & (SET_F_INTERVAL)) { + printf("\t\tflags "); + if (set->flags & SET_F_INTERVAL) { + printf("%sinterval", delim); + delim = ","; + } + printf("\n"); + } if (set->init != NULL && set->init->size > 0) { printf("\t\telements = "); diff --git a/src/scanner.l b/src/scanner.l index 25fbc610..904d6fbc 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -256,6 +256,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "position" { return POSITION; } +"interval" { return INTERVAL; } + "counter" { return COUNTER; } "packets" { return PACKETS; } "bytes" { return BYTES; } -- cgit v1.2.3 From bea7aab38f305bb8c2e400d575e6bd0a3c6bbc1f Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 16 Jan 2014 20:01:56 +0000 Subject: set: make set initializer parsable If a set contains elements, the output is not parsable since the elements = { ... } is not understood by the parser. Fix this and also add support for creating constant sets (which only makes sense when using an initializer). Signed-off-by: Patrick McHardy --- src/evaluate.c | 6 ++++++ src/parser.y | 15 ++++++++++++++- src/rule.c | 6 +++++- src/scanner.l | 2 ++ 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/evaluate.c b/src/evaluate.c index 94fee64b..21ca5581 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -1210,6 +1210,12 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set) return set_error(ctx, set, "unqualified key data type " "specified in %s definition", type); + if (set->init != NULL) { + expr_set_context(&ctx->ectx, set->keytype, set->keylen); + if (expr_evaluate(ctx, &set->init) < 0) + return -1; + } + if (!(set->flags & SET_F_MAP)) return 0; diff --git a/src/parser.y b/src/parser.y index 1b09e616..345d8d06 100644 --- a/src/parser.y +++ b/src/parser.y @@ -182,7 +182,9 @@ static void location_update(struct location *loc, struct location *rhs, int n) %token RETURN "return" %token QUEUE "queue" +%token CONSTANT "constant" %token INTERVAL "interval" +%token ELEMENTS "elements" %token NUM "number" %token STRING "string" @@ -746,6 +748,11 @@ set_block : /* empty */ { $$ = $-1; } $1->flags = $3; $$ = $1; } + | set_block ELEMENTS '=' set_expr + { + $1->init = $4; + $$ = $1; + } ; set_flag_list : set_flag_list COMMA set_flag @@ -755,7 +762,8 @@ set_flag_list : set_flag_list COMMA set_flag | set_flag ; -set_flag : INTERVAL { $$ = SET_F_INTERVAL; } +set_flag : CONSTANT { $$ = SET_F_CONSTANT; } + | INTERVAL { $$ = SET_F_INTERVAL; } ; map_block_alloc : /* empty */ @@ -793,6 +801,11 @@ map_block : /* empty */ { $$ = $-1; } $1->flags = $3; $$ = $1; } + | map_block ELEMENTS '=' set_expr + { + $1->init = $4; + $$ = $1; + } ; hook_spec : TYPE STRING HOOK STRING PRIORITY NUM diff --git a/src/rule.c b/src/rule.c index 0f7f4b51..9f6c04bb 100644 --- a/src/rule.c +++ b/src/rule.c @@ -100,8 +100,12 @@ void set_print(const struct set *set) printf(" : %s", set->datatype->name); printf("\n"); - if (set->flags & (SET_F_INTERVAL)) { + if (set->flags & (SET_F_CONSTANT | SET_F_INTERVAL)) { printf("\t\tflags "); + if (set->flags & SET_F_CONSTANT) { + printf("%sconstant", delim); + delim = ","; + } if (set->flags & SET_F_INTERVAL) { printf("%sinterval", delim); delim = ","; diff --git a/src/scanner.l b/src/scanner.l index 904d6fbc..c47e6101 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -256,7 +256,9 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "position" { return POSITION; } +"constant" { return CONSTANT; } "interval" { return INTERVAL; } +"elements" { return ELEMENTS; } "counter" { return COUNTER; } "packets" { return PACKETS; } -- cgit v1.2.3