extern const struct datatype *
set_datatype_alloc(const struct datatype *orig_dtype, unsigned int byteorder);
-extern void set_datatype_destroy(const struct datatype *dtype);
extern void time_print(uint64_t msec, struct output_ctx *octx);
extern struct error_record *time_parse(const struct location *loc,
struct netlink_mon_handler *monh);
enum nft_data_types dtype_map_to_kernel(const struct datatype *dtype);
-const struct datatype *dtype_map_from_kernel(enum nft_data_types type);
#endif /* NFTABLES_NETLINK_H */
* @gc_int: garbage collection interval
* @timeout: default timeout value
* @key: key expression (data type, length))
- * @datatype: mapping data type
- * @datalen: mapping data len
+ * @data: mapping data expression
* @objtype: mapping object type
* @init: initializer
* @rg_cache: cached range element (left)
uint32_t gc_int;
uint64_t timeout;
struct expr *key;
- const struct datatype *datatype;
- unsigned int datalen;
+ struct expr *data;
uint32_t objtype;
struct expr *init;
struct expr *rg_cache;
return dtype;
}
-void set_datatype_destroy(const struct datatype *dtype)
-{
- datatype_free(dtype);
-}
-
static struct error_record *time_unit_parse(const struct location *loc,
const char *str, uint64_t *unit)
{
{
struct expr_ctx ectx = ctx->ectx;
struct expr *map = *expr, *mappings;
+ const struct datatype *dtype;
struct expr *key;
expr_set_context(&ctx->ectx, NULL, 0);
mappings = implicit_set_declaration(ctx, "__map%d",
key,
mappings);
- mappings->set->datatype =
- datatype_get(set_datatype_alloc(ectx.dtype,
- ectx.byteorder));
- mappings->set->datalen = ectx.len;
+
+ dtype = set_datatype_alloc(ectx.dtype, ectx.byteorder);
+
+ mappings->set->data = constant_expr_alloc(&netlink_location,
+ dtype, dtype->byteorder,
+ ectx.len, NULL);
+ if (ectx.len && mappings->set->data->len != ectx.len)
+ BUG("%d vs %d\n", mappings->set->data->len, ectx.len);
map->mappings = mappings;
map->mappings->set->key->dtype->desc,
map->map->dtype->desc);
- datatype_set(map, map->mappings->set->datatype);
+ datatype_set(map, map->mappings->set->data->dtype);
map->flags |= EXPR_F_CONSTANT;
/* Data for range lookups needs to be in big endian order */
"Key must be a constant");
mapping->flags |= mapping->left->flags & EXPR_F_SINGLETON;
- expr_set_context(&ctx->ectx, set->datatype, set->datalen);
+ if (set->data) {
+ expr_set_context(&ctx->ectx, set->data->dtype, set->data->len);
+ } else {
+ assert((set->flags & NFT_SET_MAP) == 0);
+ }
+
if (expr_evaluate(ctx, &mapping->right) < 0)
return -1;
if (!expr_is_constant(mapping->right))
(*expr)->len);
else if ((*expr)->dtype->type != TYPE_INTEGER &&
!datatype_equal((*expr)->dtype, dtype))
- return stmt_binary_error(ctx, *expr, stmt,
+ return stmt_binary_error(ctx, *expr, stmt, /* verdict vs invalid? */
"datatype mismatch: expected %s, "
"expression has type %s",
dtype->desc, (*expr)->dtype->desc);
"Key expression comments are not supported");
if (stmt_evaluate_arg(ctx, stmt,
- stmt->map.set->set->datatype,
- stmt->map.set->set->datalen,
- stmt->map.set->set->datatype->byteorder,
+ stmt->map.set->set->data->dtype,
+ stmt->map.set->set->data->len,
+ stmt->map.set->set->data->byteorder,
&stmt->map.data->key) < 0)
return -1;
if (expr_is_constant(stmt->map.data))
mappings = implicit_set_declaration(ctx, "__objmap%d",
key, mappings);
- mappings->set->datatype = &string_type;
- mappings->set->datalen = NFT_OBJ_MAXNAMELEN * BITS_PER_BYTE;
+
+ mappings->set->data = constant_expr_alloc(&netlink_location,
+ &string_type,
+ BYTEORDER_HOST_ENDIAN,
+ NFT_OBJ_MAXNAMELEN * BITS_PER_BYTE,
+ NULL);
mappings->set->objtype = stmt->objref.type;
map->mappings = mappings;
map->mappings->set->key->dtype->desc,
map->map->dtype->desc);
- datatype_set(map, map->mappings->set->datatype);
+ datatype_set(map, map->mappings->set->data->dtype);
map->flags |= EXPR_F_CONSTANT;
/* Data for range lookups needs to be in big endian order */
return set_error(ctx, set, "concatenated types not supported in interval sets");
if (set_is_datamap(set->flags)) {
- if (set->datatype == NULL)
+ if (set->data == NULL)
return set_error(ctx, set, "map definition does not "
"specify mapping data type");
- set->datalen = set->datatype->size;
- if (set->datalen == 0 && set->datatype->type != TYPE_VERDICT)
+ if (set->data->len == 0 && set->data->dtype->type != TYPE_VERDICT)
return set_error(ctx, set, "unqualified mapping data "
"type specified in map definition");
} else if (set_is_objmap(set->flags)) {
- set->datatype = &string_type;
- set->datalen = NFT_OBJ_MAXNAMELEN * BITS_PER_BYTE;
+ if (set->data) {
+ assert(set->data->etype == EXPR_VALUE);
+ assert(set->data->dtype == &string_type);
+ }
+
+ assert(set->data == NULL);
+ set->data = constant_expr_alloc(&netlink_location, &string_type,
+ BYTEORDER_HOST_ENDIAN,
+ NFT_OBJ_MAXNAMELEN * BITS_PER_BYTE,
+ NULL);
+
}
ctx->set = set;
{
expr_print(expr->map, octx);
if (expr->mappings->etype == EXPR_SET_REF &&
- expr->mappings->set->datatype->type == TYPE_VERDICT)
+ expr->mappings->set->data->dtype->type == TYPE_VERDICT)
nft_print(octx, " vmap ");
else
nft_print(octx, " map ");
if (set_is_datamap(set->flags)) {
type = "map";
- datatype_ext = set->datatype->name;
+ datatype_ext = set->data->dtype->name;
} else if (set_is_objmap(set->flags)) {
type = "map";
datatype_ext = obj_type_name(set->objtype);
const char *type = "map";
if (expr->mappings->etype == EXPR_SET_REF &&
- expr->mappings->set->datatype->type == TYPE_VERDICT)
+ expr->mappings->set->data->dtype->type == TYPE_VERDICT)
type = "vmap";
return json_pack("{s:{s:o, s:o}}", type,
div_round_up(set->key->len, BITS_PER_BYTE));
if (set_is_datamap(set->flags)) {
nftnl_set_set_u32(nls, NFTNL_SET_DATA_TYPE,
- dtype_map_to_kernel(set->datatype));
+ dtype_map_to_kernel(set->data->dtype));
nftnl_set_set_u32(nls, NFTNL_SET_DATA_LEN,
- set->datalen / BITS_PER_BYTE);
+ set->data->len / BITS_PER_BYTE);
}
if (set_is_objmap(set->flags))
nftnl_set_set_u32(nls, NFTNL_SET_OBJ_TYPE, set->objtype);
if (set_is_datamap(set->flags) &&
!nftnl_udata_put_u32(udbuf, NFTNL_UDATA_SET_DATABYTEORDER,
- set->datatype->byteorder))
+ set->data->byteorder))
memory_allocation_error();
if (set->automerge &&
*/
dummyset = set_alloc(monh->loc);
dummyset->key = expr_clone(set->key);
- dummyset->datatype = set->datatype;
+ dummyset->data = set->data;
dummyset->flags = set->flags;
dummyset->init = set_expr_alloc(monh->loc, set);
}
}
-const struct datatype *dtype_map_from_kernel(enum nft_data_types type)
+static const struct datatype *dtype_map_from_kernel(enum nft_data_types type)
{
switch (type) {
case NFT_DATA_VERDICT:
const struct nftnl_set *nls)
{
const struct nftnl_udata *ud[NFTNL_UDATA_SET_MAX + 1] = {};
- uint32_t flags, key, data, data_len, objtype = 0;
enum byteorder keybyteorder = BYTEORDER_INVALID;
enum byteorder databyteorder = BYTEORDER_INVALID;
- const struct datatype *keytype, *datatype;
+ const struct datatype *keytype, *datatype = NULL;
+ uint32_t flags, key, objtype = 0;
bool automerge = false;
const char *udata;
struct set *set;
flags = nftnl_set_get_u32(nls, NFTNL_SET_FLAGS);
if (set_is_datamap(flags)) {
+ uint32_t data;
+
data = nftnl_set_get_u32(nls, NFTNL_SET_DATA_TYPE);
datatype = dtype_map_from_kernel(data);
if (datatype == NULL) {
data);
return NULL;
}
- } else
- datatype = NULL;
+ }
if (set_is_objmap(flags)) {
objtype = nftnl_set_get_u32(nls, NFTNL_SET_OBJ_TYPE);
set->objtype = objtype;
+ set->data = NULL;
if (datatype)
- set->datatype = datatype_get(set_datatype_alloc(datatype,
- databyteorder));
- else
- set->datatype = NULL;
-
- if (nftnl_set_is_set(nls, NFTNL_SET_DATA_LEN)) {
- data_len = nftnl_set_get_u32(nls, NFTNL_SET_DATA_LEN);
- set->datalen = data_len * BITS_PER_BYTE;
- }
+ set->data = constant_expr_alloc(&netlink_location,
+ set_datatype_alloc(datatype, databyteorder),
+ databyteorder,
+ nftnl_set_get_u32(nls, NFTNL_SET_DATA_LEN) * BITS_PER_BYTE,
+ NULL);
if (nftnl_set_is_set(nls, NFTNL_SET_TIMEOUT))
set->timeout = nftnl_set_get_u64(nls, NFTNL_SET_TIMEOUT);
goto out;
data = netlink_alloc_data(&netlink_location, &nld,
- set->datatype->type == TYPE_VERDICT ?
+ set->data->dtype->type == TYPE_VERDICT ?
NFT_REG_VERDICT : NFT_REG_1);
- datatype_set(data, set->datatype);
- data->byteorder = set->datatype->byteorder;
+ datatype_set(data, set->data->dtype);
+ data->byteorder = set->data->byteorder;
if (data->byteorder == BYTEORDER_HOST_ENDIAN)
mpz_switch_byteorder(data->value, data->len / BITS_PER_BYTE);
stmt_separator
{
$1->key = $3;
- $1->datatype = $5->dtype;
+ $1->data = $5;
- expr_free($5);
$1->flags |= NFT_SET_MAP;
$$ = $1;
}
}
if (!json_unpack(root, "{s:s}", "map", &dtype_ext)) {
+ const struct datatype *dtype;
+
set->objtype = string_to_nft_object(dtype_ext);
if (set->objtype) {
set->flags |= NFT_SET_OBJECT;
- } else if (datatype_lookup_byname(dtype_ext)) {
- set->datatype = datatype_lookup_byname(dtype_ext);
+ } else if ((dtype = datatype_lookup_byname(dtype_ext))) {
+ set->data = constant_expr_alloc(&netlink_location,
+ dtype, dtype->byteorder,
+ dtype->size, NULL);
set->flags |= NFT_SET_MAP;
} else {
json_error(ctx, "Invalid map type '%s'.", dtype_ext);
new_set->gc_int = set->gc_int;
new_set->timeout = set->timeout;
new_set->key = expr_clone(set->key);
- new_set->datatype = datatype_get(set->datatype);
- new_set->datalen = set->datalen;
+ if (set->data)
+ new_set->data = expr_clone(set->data);
new_set->objtype = set->objtype;
new_set->policy = set->policy;
new_set->automerge = set->automerge;
expr_free(set->init);
handle_free(&set->handle);
expr_free(set->key);
- set_datatype_destroy(set->datatype);
+ expr_free(set->data);
xfree(set);
}
nft_print(octx, "%s%stype %s",
opts->tab, opts->tab, set->key->dtype->name);
if (set_is_datamap(set->flags))
- nft_print(octx, " : %s", set->datatype->name);
+ nft_print(octx, " : %s", set->data->dtype->name);
else if (set_is_objmap(set->flags))
nft_print(octx, " : %s", obj_type_name(set->objtype));
tree->root = RB_ROOT;
tree->keytype = set->key->dtype;
tree->keylen = set->key->len;
- tree->datatype = set->datatype;
- tree->datalen = set->datalen;
+ tree->datatype = NULL;
+ tree->datalen = 0;
+ if (set->data) {
+ tree->datatype = set->data->dtype;
+ tree->datalen = set->data->len;
+ }
tree->byteorder = first->byteorder;
tree->debug_mask = debug_mask;
}