diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/evaluate.c | 62 | ||||
-rw-r--r-- | src/expression.c | 4 | ||||
-rw-r--r-- | src/netlink.c | 27 | ||||
-rw-r--r-- | src/netlink_delinearize.c | 12 | ||||
-rw-r--r-- | src/parser_bison.y | 65 | ||||
-rw-r--r-- | src/rule.c | 4 | ||||
-rw-r--r-- | src/segtree.c | 4 |
7 files changed, 98 insertions, 80 deletions
diff --git a/src/evaluate.c b/src/evaluate.c index 86159cf5..836c9528 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -60,6 +60,18 @@ static int __fmtstring(3, 4) set_error(struct eval_ctx *ctx, return -1; } +static void key_fix_dtype_byteorder(struct expr *key) +{ + const struct datatype *dtype = key->dtype; + + if (dtype->byteorder == key->byteorder) + return; + + key->dtype = set_datatype_alloc(dtype, key->byteorder); + if (dtype->flags & DTYPE_F_ALLOC) + concat_type_destroy(dtype); +} + static struct expr *implicit_set_declaration(struct eval_ctx *ctx, const char *name, struct expr *key, @@ -69,11 +81,12 @@ static struct expr *implicit_set_declaration(struct eval_ctx *ctx, struct set *set; struct handle h; + key_fix_dtype_byteorder(key); + set = set_alloc(&expr->location); set->flags = NFT_SET_ANONYMOUS | expr->set_flags; - set->handle.set = xstrdup(name), - set->keytype = set_datatype_alloc(key->dtype, key->byteorder); - set->keylen = key->len; + set->handle.set = xstrdup(name); + set->key = key; set->init = expr; if (ctx->table != NULL) @@ -1204,8 +1217,6 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr) mappings = implicit_set_declaration(ctx, "__map%d", key, mappings); - expr_free(key); - mappings->set->datatype = set_datatype_alloc(ectx.dtype, ectx.byteorder); mappings->set->datalen = ectx.len; @@ -1232,11 +1243,11 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr) map->mappings->ops->name); } - if (!datatype_equal(map->map->dtype, map->mappings->set->keytype)) + if (!datatype_equal(map->map->dtype, map->mappings->set->key->dtype)) return expr_binary_error(ctx->msgs, map->mappings, map->map, "datatype mismatch, map expects %s, " "mapping expression has type %s", - map->mappings->set->keytype->desc, + map->mappings->set->key->dtype->desc, map->map->dtype->desc); map->dtype = map->mappings->set->datatype; @@ -1261,7 +1272,7 @@ static int expr_evaluate_mapping(struct eval_ctx *ctx, struct expr **expr) if (!(set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))) return set_error(ctx, set, "set is not a map"); - expr_set_context(&ctx->ectx, set->keytype, set->keylen); + expr_set_context(&ctx->ectx, set->key->dtype, set->key->len); if (expr_evaluate(ctx, &mapping->left) < 0) return -1; if (!expr_is_constant(mapping->left)) @@ -2589,9 +2600,9 @@ static int stmt_evaluate_set(struct eval_ctx *ctx, struct stmt *stmt) "Expression does not refer to a set"); if (stmt_evaluate_arg(ctx, stmt, - stmt->set.set->set->keytype, - stmt->set.set->set->keylen, - stmt->set.set->set->keytype->byteorder, + stmt->set.set->set->key->dtype, + stmt->set.set->set->key->len, + stmt->set.set->set->key->byteorder, &stmt->set.key) < 0) return -1; if (expr_is_constant(stmt->set.key)) @@ -2629,8 +2640,6 @@ static int stmt_evaluate_objref_map(struct eval_ctx *ctx, struct stmt *stmt) mappings = implicit_set_declaration(ctx, "__objmap%d", key, mappings); - expr_free(key); - mappings->set->datatype = &string_type; mappings->set->datalen = NFT_OBJ_MAXNAMELEN * BITS_PER_BYTE; mappings->set->objtype = stmt->objref.type; @@ -2657,11 +2666,11 @@ static int stmt_evaluate_objref_map(struct eval_ctx *ctx, struct stmt *stmt) map->mappings->ops->name); } - if (!datatype_equal(map->map->dtype, map->mappings->set->keytype)) + if (!datatype_equal(map->map->dtype, map->mappings->set->key->dtype)) return expr_binary_error(ctx->msgs, map->mappings, map->map, "datatype mismatch, map expects %s, " "mapping expression has type %s", - map->mappings->set->keytype->desc, + map->mappings->set->key->dtype->desc, map->map->dtype->desc); map->dtype = map->mappings->set->datatype; @@ -2765,7 +2774,7 @@ static int setelem_evaluate(struct eval_ctx *ctx, struct expr **expr) ctx->cmd->handle.set); ctx->set = set; - expr_set_context(&ctx->ectx, set->keytype, set->keylen); + expr_set_context(&ctx->ectx, set->key->dtype, set->key->len); if (expr_evaluate(ctx, expr) < 0) return -1; ctx->set = NULL; @@ -2784,15 +2793,20 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set) type = set->flags & NFT_SET_MAP ? "map" : "set"; - if (set->keytype == NULL) - return set_error(ctx, set, "%s definition does not specify " - "key data type", type); + if (set->key == NULL) + return set_error(ctx, set, "%s definition does not specify key", + type); - set->keylen = set->keytype->size; - if (set->keylen == 0) - return set_error(ctx, set, "unqualified key data type " - "specified in %s definition", type); + if (set->key->len == 0) { + if (set->key->ops->type == EXPR_CONCAT && + expr_evaluate_concat(ctx, &set->key) < 0) + return -1; + if (set->key->len == 0) + return set_error(ctx, set, "unqualified key type %s " + "specified in %s definition", + set->key->dtype->name, type); + } if (set->flags & NFT_SET_MAP) { if (set->datatype == NULL) return set_error(ctx, set, "map definition does not " @@ -2809,7 +2823,7 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set) ctx->set = set; if (set->init != NULL) { - expr_set_context(&ctx->ectx, set->keytype, set->keylen); + expr_set_context(&ctx->ectx, set->key->dtype, set->key->len); if (expr_evaluate(ctx, &set->init) < 0) return -1; } diff --git a/src/expression.c b/src/expression.c index d41ada39..ff3550c7 100644 --- a/src/expression.c +++ b/src/expression.c @@ -832,7 +832,7 @@ struct expr *set_expr_alloc(const struct location *loc, const struct set *set) return set_expr; set_expr->set_flags = set->flags; - set_expr->dtype = set->keytype; + set_expr->dtype = set->key->dtype; return set_expr; } @@ -960,7 +960,7 @@ struct expr *set_ref_expr_alloc(const struct location *loc, struct set *set) { struct expr *expr; - expr = expr_alloc(loc, &set_ref_expr_ops, set->keytype, 0, 0); + expr = expr_alloc(loc, &set_ref_expr_ops, set->key->dtype, 0, 0); expr->set = set_get(set); expr->flags |= EXPR_F_CONSTANT; return expr; diff --git a/src/netlink.c b/src/netlink.c index 291bbdee..e414718b 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -1118,8 +1118,11 @@ static struct set *netlink_delinearize_set(struct netlink_ctx *ctx, set->handle.table = xstrdup(nftnl_set_get_str(nls, NFTNL_SET_TABLE)); set->handle.set = xstrdup(nftnl_set_get_str(nls, NFTNL_SET_NAME)); - set->keytype = set_datatype_alloc(keytype, keybyteorder); - set->keylen = nftnl_set_get_u32(nls, NFTNL_SET_KEY_LEN) * BITS_PER_BYTE; + set->key = constant_expr_alloc(&netlink_location, + set_datatype_alloc(keytype, keybyteorder), + keybyteorder, + nftnl_set_get_u32(nls, NFTNL_SET_KEY_LEN) * BITS_PER_BYTE, + NULL); set->flags = nftnl_set_get_u32(nls, NFTNL_SET_FLAGS); set->objtype = objtype; @@ -1158,9 +1161,9 @@ static int netlink_add_set_compat(struct netlink_ctx *ctx, nls = alloc_nftnl_set(h); nftnl_set_set_u32(nls, NFTNL_SET_FLAGS, set->flags); nftnl_set_set_u32(nls, NFTNL_SET_KEY_TYPE, - dtype_map_to_kernel(set->keytype)); + dtype_map_to_kernel(set->key->dtype)); nftnl_set_set_u32(nls, NFTNL_SET_KEY_LEN, - div_round_up(set->keylen, BITS_PER_BYTE)); + div_round_up(set->key->len, BITS_PER_BYTE)); if (set->flags & NFT_SET_MAP) { nftnl_set_set_u32(nls, NFTNL_SET_DATA_TYPE, dtype_map_to_kernel(set->datatype)); @@ -1192,9 +1195,9 @@ static int netlink_add_set_batch(struct netlink_ctx *ctx, nls = alloc_nftnl_set(h); nftnl_set_set_u32(nls, NFTNL_SET_FLAGS, set->flags); nftnl_set_set_u32(nls, NFTNL_SET_KEY_TYPE, - dtype_map_to_kernel(set->keytype)); + dtype_map_to_kernel(set->key->dtype)); nftnl_set_set_u32(nls, NFTNL_SET_KEY_LEN, - div_round_up(set->keylen, BITS_PER_BYTE)); + div_round_up(set->key->len, BITS_PER_BYTE)); if (set->flags & NFT_SET_MAP) { nftnl_set_set_u32(nls, NFTNL_SET_DATA_TYPE, dtype_map_to_kernel(set->datatype)); @@ -1226,7 +1229,7 @@ static int netlink_add_set_batch(struct netlink_ctx *ctx, if (!udbuf) memory_allocation_error(); if (!nftnl_udata_put_u32(udbuf, UDATA_SET_KEYBYTEORDER, - set->keytype->byteorder)) + set->key->byteorder)) memory_allocation_error(); if (set->flags & NFT_SET_MAP && @@ -1537,10 +1540,10 @@ static int netlink_delinearize_setelem(struct nftnl_set_elem *nlse, flags = nftnl_set_elem_get_u32(nlse, NFTNL_SET_ELEM_FLAGS); key = netlink_alloc_value(&netlink_location, &nld); - key->dtype = set->keytype; - key->byteorder = set->keytype->byteorder; - if (set->keytype->subtypes) - key = netlink_parse_concat_elem(set->keytype, key); + key->dtype = set->key->dtype; + key->byteorder = set->key->byteorder; + if (set->key->dtype->subtypes) + key = netlink_parse_concat_elem(set->key->dtype, key); if (!(set->flags & NFT_SET_INTERVAL) && key->byteorder == BYTEORDER_HOST_ENDIAN) @@ -2197,7 +2200,7 @@ static int netlink_events_setelem_cb(const struct nlmsghdr *nlh, int type, * used by named sets, so use a dummy set. */ dummyset = set_alloc(monh->loc); - dummyset->keytype = set->keytype; + dummyset->key = expr_clone(set->key); dummyset->datatype = set->datatype; dummyset->flags = set->flags; dummyset->init = set_expr_alloc(monh->loc, set); diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index 3f42d092..42206ebc 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -307,8 +307,8 @@ static void netlink_parse_lookup(struct netlink_parse_ctx *ctx, return netlink_error(ctx, loc, "Lookup expression has no left hand side"); - if (left->len < set->keylen) { - left = netlink_parse_concat_expr(ctx, loc, sreg, set->keylen); + if (left->len < set->key->len) { + left = netlink_parse_concat_expr(ctx, loc, sreg, set->key->len); if (left == NULL) return; } @@ -1122,8 +1122,8 @@ static void netlink_parse_dynset(struct netlink_parse_ctx *ctx, return netlink_error(ctx, loc, "Dynset statement has no key expression"); - if (expr->len < set->keylen) { - expr = netlink_parse_concat_expr(ctx, loc, sreg, set->keylen); + if (expr->len < set->key->len) { + expr = netlink_parse_concat_expr(ctx, loc, sreg, set->key->len); if (expr == NULL) return; } @@ -1193,8 +1193,8 @@ static void netlink_parse_objref(struct netlink_parse_ctx *ctx, return netlink_error(ctx, loc, "objref expression has no left hand side"); - if (left->len < set->keylen) { - left = netlink_parse_concat_expr(ctx, loc, sreg, set->keylen); + if (left->len < set->key->len) { + left = netlink_parse_concat_expr(ctx, loc, sreg, set->key->len); if (left == NULL) return; } diff --git a/src/parser_bison.y b/src/parser_bison.y index 970d773e..c7ba1495 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -478,8 +478,8 @@ static void location_update(struct location *loc, struct location *rhs, int n) %type <val> time_spec quota_used -%type <val> type_identifier_list -%type <datatype> data_type +%type <expr> data_type_expr data_type_atom_expr +%destructor { expr_free($$); } data_type_expr data_type_atom_expr %type <cmd> line %destructor { cmd_free($$); } line @@ -1405,9 +1405,9 @@ set_block_alloc : /* empty */ set_block : /* empty */ { $$ = $<set>-1; } | set_block common_block | set_block stmt_separator - | set_block TYPE data_type stmt_separator + | set_block TYPE data_type_expr stmt_separator { - $1->keytype = $3; + $1->key = $3; $$ = $1; } | set_block FLAGS set_flag_list stmt_separator @@ -1459,28 +1459,30 @@ map_block : /* empty */ { $$ = $<set>-1; } | map_block common_block | map_block stmt_separator | map_block TYPE - data_type COLON data_type + data_type_expr COLON data_type_expr stmt_separator { - $1->keytype = $3; - $1->datatype = $5; + $1->key = $3; + $1->datatype = $5->dtype; + + expr_free($5); $1->flags |= NFT_SET_MAP; $$ = $1; } | map_block TYPE - data_type COLON COUNTER + data_type_expr COLON COUNTER stmt_separator { - $1->keytype = $3; + $1->key = $3; $1->objtype = NFT_OBJECT_COUNTER; $1->flags |= NFT_SET_OBJECT; $$ = $1; } | map_block TYPE - data_type COLON QUOTA + data_type_expr COLON QUOTA stmt_separator { - $1->keytype = $3; + $1->key = $3; $1->objtype = NFT_OBJECT_QUOTA; $1->flags |= NFT_SET_OBJECT; $$ = $1; @@ -1512,16 +1514,7 @@ set_policy_spec : PERFORMANCE { $$ = NFT_SET_POL_PERFORMANCE; } | MEMORY { $$ = NFT_SET_POL_MEMORY; } ; -data_type : type_identifier_list - { - if ($1 & ~TYPE_MASK) - $$ = concat_type_alloc($1); - else - $$ = datatype_lookup($1); - } - ; - -type_identifier_list : type_identifier +data_type_atom_expr : type_identifier { const struct datatype *dtype = datatype_lookup_byname($1); if (dtype == NULL) { @@ -1530,20 +1523,28 @@ type_identifier_list : type_identifier xfree($1); YYERROR; } - xfree($1); - $$ = dtype->type; + $$ = constant_expr_alloc(&@1, dtype, dtype->byteorder, + dtype->size, NULL); } - | type_identifier_list DOT type_identifier + ; + +data_type_expr : data_type_atom_expr + | data_type_expr DOT data_type_atom_expr { - const struct datatype *dtype = datatype_lookup_byname($3); - if (dtype == NULL) { - erec_queue(error(&@3, "unknown datatype %s", $3), - state->msgs); - xfree($3); - YYERROR; + if ($1->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 = @$; } - xfree($3); - $$ = concat_subtype_add($$, dtype->type); + compound_expr_add($$, $3); } ; @@ -215,7 +215,7 @@ void set_free(struct set *set) if (set->init != NULL) expr_free(set->init); handle_free(&set->handle); - set_datatype_destroy(set->keytype); + expr_free(set->key); set_datatype_destroy(set->datatype); xfree(set); } @@ -296,7 +296,7 @@ static void set_print_declaration(const struct set *set, printf(" %s {%s", set->handle.set, opts->nl); - printf("%s%stype %s", opts->tab, opts->tab, set->keytype->name); + printf("%s%stype %s", opts->tab, opts->tab, set->key->dtype->name); if (set->flags & NFT_SET_MAP) printf(" : %s", set->datatype->name); else if (set->flags & NFT_SET_OBJECT) diff --git a/src/segtree.c b/src/segtree.c index f81e1174..f0efd155 100644 --- a/src/segtree.c +++ b/src/segtree.c @@ -76,8 +76,8 @@ static void seg_tree_init(struct seg_tree *tree, const struct set *set, first = list_entry(init->expressions.next, struct expr, list); tree->root = RB_ROOT; - tree->keytype = set->keytype; - tree->keylen = set->keylen; + tree->keytype = set->key->dtype; + tree->keylen = set->key->len; tree->datatype = set->datatype; tree->datalen = set->datalen; tree->byteorder = first->byteorder; |