From 0bd59cf4daff00e10b4152acad593c548e344a18 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 15 Jan 2014 21:12:38 +0100 Subject: parser: fix parsing of ethernet protocol types This allows us to use the protocol type keyword, eg. nft add rule ip filter output meta protocol ip6 counter ^^^ Signed-off-by: Pablo Neira Ayuso --- src/parser.y | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'src') diff --git a/src/parser.y b/src/parser.y index 038282ec..23662f78 100644 --- a/src/parser.y +++ b/src/parser.y @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "parser.h" @@ -1418,6 +1419,13 @@ vlan_hdr_expr : VLAN vlan_hdr_field { $$ = payload_expr_alloc(&@$, &payload_vlan, $2); } + | VLAN + { + uint16_t data = ETH_P_8021Q; + $$ = constant_expr_alloc(&@$, ðertype_type, + BYTEORDER_HOST_ENDIAN, + sizeof(data) * BITS_PER_BYTE, &data); + } ; vlan_hdr_field : ID { $$ = VLANHDR_VID; } @@ -1430,6 +1438,13 @@ arp_hdr_expr : ARP arp_hdr_field { $$ = payload_expr_alloc(&@$, &payload_arp, $2); } + | ARP + { + uint16_t data = ETH_P_ARP; + $$ = constant_expr_alloc(&@$, ðertype_type, + BYTEORDER_HOST_ENDIAN, + sizeof(data) * BITS_PER_BYTE, &data); + } ; arp_hdr_field : HTYPE { $$ = ARPHDR_HRD; } @@ -1443,6 +1458,13 @@ ip_hdr_expr : IP ip_hdr_field { $$ = payload_expr_alloc(&@$, &payload_ip, $2); } + | IP + { + uint16_t data = ETH_P_IP; + $$ = constant_expr_alloc(&@$, ðertype_type, + BYTEORDER_HOST_ENDIAN, + sizeof(data) * BITS_PER_BYTE, &data); + } ; ip_hdr_field : VERSION { $$ = IPHDR_VERSION; } @@ -1484,6 +1506,13 @@ ip6_hdr_expr : IP6 ip6_hdr_field { $$ = payload_expr_alloc(&@$, &payload_ip6, $2); } + | IP6 + { + uint16_t data = ETH_P_IPV6; + $$ = constant_expr_alloc(&@$, ðertype_type, + BYTEORDER_HOST_ENDIAN, + sizeof(data) * BITS_PER_BYTE, &data); + } ; ip6_hdr_field : VERSION { $$ = IP6HDR_VERSION; } -- cgit v1.2.3 From 4a6d434f6fe830e9b6e5663715b605687f1c3897 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 15 Jan 2014 21:19:02 +0100 Subject: payload: fix crash when wrong ethernet protocol type is used nft add rule ip filter output meta protocol xyz counter ^^^ This fix is similar to 4097ad7 ("meta: fix crash when parsing unresolvable mark values"). Signed-off-by: Pablo Neira Ayuso --- src/payload.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/payload.c b/src/payload.c index 86d75fa5..decfcd61 100644 --- a/src/payload.c +++ b/src/payload.c @@ -993,6 +993,7 @@ static struct error_record *ethertype_parse(const struct expr *sym, { struct error_record *erec; + *res = NULL; erec = sym->dtype->basetype->parse(sym, res); if (erec != NULL) return erec; -- cgit v1.2.3 From 3bbc269d4acc803b82190ad5f0c6de06609f51b3 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 15 Jan 2014 21:20:37 +0100 Subject: payload: fix inconsistency in ethertype output Use ip6 instead of ipv6. Signed-off-by: Pablo Neira Ayuso --- src/payload.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/payload.c b/src/payload.c index decfcd61..bfd8ba4d 100644 --- a/src/payload.c +++ b/src/payload.c @@ -982,7 +982,7 @@ static const struct symbol_table ethertype_tbl = { .symbols = { SYMBOL("ip", ETH_P_IP), SYMBOL("arp", ETH_P_ARP), - SYMBOL("ipv6", ETH_P_IPV6), + SYMBOL("ip6", ETH_P_IPV6), SYMBOL("vlan", ETH_P_8021Q), SYMBOL_LIST_END }, -- cgit v1.2.3 From 734eed347ff1b648b57940af482452d09337282c Mon Sep 17 00:00:00 2001 From: Pablo Neira Date: Mon, 13 Jan 2014 13:39:16 +0100 Subject: expression: fix output of verdict maps % nft list table filter table ip filter { ... chain output { ... ip saddr map { 1.1.1.1 => accept} } } It displays 'map' instead of 'vmap'. Fix it by checking the mapping type in map_expr_print(). Signed-off-by: Pablo Neira Ayuso --- src/expression.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expression.c b/src/expression.c index 518f71c8..a12133c8 100644 --- a/src/expression.c +++ b/src/expression.c @@ -691,7 +691,11 @@ struct expr *mapping_expr_alloc(const struct location *loc, static void map_expr_print(const struct expr *expr) { expr_print(expr->map); - printf(" map "); + if (expr->mappings->ops->type == EXPR_SET_REF && + expr->mappings->set->datatype->type == TYPE_VERDICT) + printf(" vmap "); + else + printf(" map "); expr_print(expr->mappings); } -- cgit v1.2.3 From 001661033e177a5f580ff49de8d1a56a2e9b8cb8 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 16 Jan 2014 17:11:12 +0000 Subject: parser: fix compilation breakage Commit 0bd59cf4da (parser: fix parsing of ethernet protocol types) broke compilation: src/parser.y:26:22: fatal error: if_ether.h: No such file or directory Should be netinet/if_ether.h. Signed-off-by: Patrick McHardy --- src/parser.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/parser.y b/src/parser.y index 23662f78..d4a79291 100644 --- a/src/parser.y +++ b/src/parser.y @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -23,7 +24,6 @@ #include #include #include -#include #include #include "parser.h" -- cgit v1.2.3 From 655fb611aecca135a3f09fe9a4c50ddb2c76a122 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 16 Jan 2014 17:11:12 +0000 Subject: segtree: only use prefix expressions for ranges for selected datatypes It is uncommon to represent f.i. port number ranges as prefix expressions. Introduce a datatype DTYPE_F_PREFIX flag to indicate that the preferred representation of a range is a prefix and use it for segtree decomposition to decide whether to use a range or prefix expression. The ipaddr, ip6addr, mark and realm datatypes are changed to include the DTYPE_F_PREFIX flag. This fixes completely unreadable output in cases where the ranges are representable as prefixes, f.i. in case of port number: { 0/6 => jump chain1, 0/5 => jump chain2, 0/4 => continue} becomes: { 0-1023 => jump chain1, 1024-2047 => jump chain2, 2048-4095 => continue} Signed-off-by: Patrick McHardy --- src/datatype.c | 3 +++ src/meta.c | 1 + src/segtree.c | 4 +++- 3 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/datatype.c b/src/datatype.c index 86ea80e3..45944907 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -380,6 +380,7 @@ const struct datatype ipaddr_type = { .basetype = &integer_type, .print = ipaddr_type_print, .parse = ipaddr_type_parse, + .flags = DTYPE_F_PREFIX, }; static void ip6addr_type_print(const struct expr *expr) @@ -437,6 +438,7 @@ const struct datatype ip6addr_type = { .basetype = &integer_type, .print = ip6addr_type_print, .parse = ip6addr_type_parse, + .flags = DTYPE_F_PREFIX, }; static void inet_protocol_type_print(const struct expr *expr) @@ -662,6 +664,7 @@ const struct datatype mark_type = { .basefmt = "0x%.8Zx", .print = mark_type_print, .parse = mark_type_parse, + .flags = DTYPE_F_PREFIX, }; static void time_type_print(const struct expr *expr) diff --git a/src/meta.c b/src/meta.c index f06a2fbd..849acd15 100644 --- a/src/meta.c +++ b/src/meta.c @@ -61,6 +61,7 @@ static const struct datatype realm_type = { .basetype = &integer_type, .print = realm_type_print, .parse = realm_type_parse, + .flags = DTYPE_F_PREFIX, }; static void tchandle_type_print(const struct expr *expr) diff --git a/src/segtree.c b/src/segtree.c index 5426e24f..e3bca4ca 100644 --- a/src/segtree.c +++ b/src/segtree.c @@ -552,7 +552,9 @@ void interval_map_decompose(struct expr *set) if (!mpz_cmp_ui(range, 0)) compound_expr_add(set, low); - else if (!range_is_prefix(range) || mpz_cmp_ui(p, 0)) { + else if ((!range_is_prefix(range) || + !(i->dtype->flags & DTYPE_F_PREFIX)) || + mpz_cmp_ui(p, 0)) { struct expr *tmp; tmp = constant_expr_alloc(&low->location, low->dtype, -- cgit v1.2.3 From 86b965bdab8dc8735c4a846ec09bfbbadfae780b Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 16 Jan 2014 17:11:12 +0000 Subject: segtree: fix decomposition of unclosed intervals If intervals are directly adjacent or extend to the right end of the dimension, they are not closed by a EXPR_F_INTERVAL_END entry. This leads to multiple errors when decomposing the intervals: - the last unclosed interval is not shown at all. - if a range is unclosed and the set is a map, the starting point of the next interval is set to the data, not the key, leading to nonsensical output. - if a prefix is unclosed, the interval is assumed to be a prefix as well and the same starting point is kept. This makes sense for cases like 192.168.0.0/24, 192.168.0.0/16, but leads to hard to understand results if the next interval is not representable as a prefix. Fix this by doing two things: - add an EXPR_F_INTERVAL_END element for each unclosed interval during preprocessing. - process the final unclosed interval extending to the right end of the dimension, if present. Signed-off-by: Patrick McHardy --- src/segtree.c | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/segtree.c b/src/segtree.c index e3bca4ca..1a21c6c1 100644 --- a/src/segtree.c +++ b/src/segtree.c @@ -509,10 +509,11 @@ static struct expr *expr_value(struct expr *expr) void interval_map_decompose(struct expr *set) { - struct expr *ranges[set->size]; - struct expr *i, *next, *low = NULL; + struct expr *ranges[set->size * 2]; + struct expr *i, *next, *low = NULL, *end; unsigned int n, size; mpz_t range, p; + bool interval; mpz_init(range); mpz_init(p); @@ -520,8 +521,20 @@ void interval_map_decompose(struct expr *set) size = set->size; n = 0; + interval = false; list_for_each_entry_safe_reverse(i, next, &set->expressions, list) { compound_expr_remove(set, i); + + if (i->flags & EXPR_F_INTERVAL_END) + interval = false; + else if (interval) { + end = expr_clone(expr_value(i)); + end->flags |= EXPR_F_INTERVAL_END; + ranges[n++] = end; + size++; + } else + interval = true; + ranges[n++] = i; } @@ -569,8 +582,6 @@ void interval_map_decompose(struct expr *set) tmp = mapping_expr_alloc(&tmp->location, tmp, low->right); compound_expr_add(set, tmp); - - low = expr_get(tmp->right); } else { struct expr *prefix; unsigned int prefix_len; @@ -578,13 +589,9 @@ void interval_map_decompose(struct expr *set) prefix_len = expr_value(i)->len - mpz_scan0(range, 0); prefix = prefix_expr_alloc(&low->location, expr_value(low), prefix_len); - - if (low->ops->type == EXPR_MAPPING) { + if (low->ops->type == EXPR_MAPPING) prefix = mapping_expr_alloc(&low->location, prefix, low->right); - /* Update mapping of "low" to the current mapping */ - low->right = expr_get(i->right); - } compound_expr_add(set, prefix); } @@ -595,4 +602,18 @@ void interval_map_decompose(struct expr *set) } expr_free(i); } + + /* Unclosed interval */ + if (low != NULL) { + i = constant_expr_alloc(&low->location, low->dtype, + low->byteorder, expr_value(low)->len, + NULL); + mpz_init_bitmask(i->value, i->len); + + i = range_expr_alloc(&low->location, expr_value(low), i); + if (low->ops->type == EXPR_MAPPING) + i = mapping_expr_alloc(&i->location, i, low->right); + + compound_expr_add(set, i); + } } -- cgit v1.2.3