diff options
-rw-r--r-- | include/datatype.h | 7 | ||||
-rw-r--r-- | src/datatype.c | 3 | ||||
-rw-r--r-- | src/expression.c | 6 | ||||
-rw-r--r-- | src/meta.c | 1 | ||||
-rw-r--r-- | src/parser.y | 29 | ||||
-rw-r--r-- | src/proto.c | 2 | ||||
-rw-r--r-- | src/segtree.c | 43 |
7 files changed, 79 insertions, 12 deletions
diff --git a/include/datatype.h b/include/datatype.h index 9f8b44ae..9e609cf2 100644 --- a/include/datatype.h +++ b/include/datatype.h @@ -85,8 +85,15 @@ enum byteorder { struct expr; +/** + * enum datatype_flags + * + * @DTYPE_F_ALLOC: datatype is dynamically allocated + * @DTYPE_F_PREFIX: preferred representation for ranges is a prefix + */ enum datatype_flags { DTYPE_F_ALLOC = (1 << 0), + DTYPE_F_PREFIX = (1 << 1), }; /** diff --git a/src/datatype.c b/src/datatype.c index e228f530..5e4aacdf 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -398,6 +398,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) @@ -455,6 +456,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) @@ -680,6 +682,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/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); } @@ -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/parser.y b/src/parser.y index 89d6279c..05fe8bcb 100644 --- a/src/parser.y +++ b/src/parser.y @@ -14,6 +14,7 @@ #include <stdio.h> #include <inttypes.h> #include <netinet/ip.h> +#include <netinet/if_ether.h> #include <linux/netfilter.h> #include <linux/netfilter/nf_tables.h> #include <linux/netfilter/nf_conntrack_tuple_common.h> @@ -1482,6 +1483,13 @@ vlan_hdr_expr : VLAN vlan_hdr_field { $$ = payload_expr_alloc(&@$, &proto_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; } @@ -1494,6 +1502,13 @@ arp_hdr_expr : ARP arp_hdr_field { $$ = payload_expr_alloc(&@$, &proto_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; } @@ -1507,6 +1522,13 @@ ip_hdr_expr : IP ip_hdr_field { $$ = payload_expr_alloc(&@$, &proto_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; } @@ -1548,6 +1570,13 @@ ip6_hdr_expr : IP6 ip6_hdr_field { $$ = payload_expr_alloc(&@$, &proto_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; } diff --git a/src/proto.c b/src/proto.c index 4d4925b0..cc073af0 100644 --- a/src/proto.c +++ b/src/proto.c @@ -743,7 +743,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 }, diff --git a/src/segtree.c b/src/segtree.c index 5426e24f..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; } @@ -552,7 +565,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, @@ -567,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; @@ -576,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); } @@ -593,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); + } } |