summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/datatype.h2
-rw-r--r--src/datatype.c21
-rw-r--r--src/evaluate.c11
3 files changed, 19 insertions, 15 deletions
diff --git a/include/datatype.h b/include/datatype.h
index ca6ba9fe..f05f9877 100644
--- a/include/datatype.h
+++ b/include/datatype.h
@@ -212,7 +212,7 @@ extern const struct datatype icmpv6_code_type;
extern const struct datatype icmpx_code_type;
extern const struct datatype time_type;
-extern const struct datatype *concat_type_alloc(const struct expr *expr);
+extern const struct datatype *concat_type_alloc(uint32_t type);
extern void concat_type_destroy(const struct datatype *dtype);
#endif /* NFTABLES_DATATYPE_H */
diff --git a/src/datatype.c b/src/datatype.c
index 91e5ed6d..2a9fcdb0 100644
--- a/src/datatype.c
+++ b/src/datatype.c
@@ -924,25 +924,28 @@ static struct datatype *dtype_alloc(void)
return dtype;
}
-const struct datatype *concat_type_alloc(const struct expr *expr)
+const struct datatype *concat_type_alloc(uint32_t type)
{
+ const struct datatype *i;
struct datatype *dtype;
- struct expr *i;
char desc[256] = "concatenation of (";
char name[256] = "";
- unsigned int type = 0, size = 0, subtypes = 0;
+ unsigned int size = 0, subtypes = 0, n;
+
+ n = div_round_up(fls(type), TYPE_BITS);
+ while ((type >> TYPE_BITS * --n) & TYPE_MASK) {
+ i = datatype_lookup((type >> TYPE_BITS * n) & TYPE_MASK);
+ if (i == NULL)
+ return NULL;
- list_for_each_entry(i, &expr->expressions, list) {
if (subtypes != 0) {
strncat(desc, ", ", sizeof(desc) - strlen(desc) - 1);
strncat(name, " . ", sizeof(name) - strlen(name) - 1);
}
- strncat(desc, i->dtype->desc, sizeof(desc) - strlen(desc) - 1);
- strncat(name, i->dtype->name, sizeof(name) - strlen(name) - 1);
+ strncat(desc, i->desc, sizeof(desc) - strlen(desc) - 1);
+ strncat(name, i->name, sizeof(name) - strlen(name) - 1);
- type <<= TYPE_BITS;
- type |= i->dtype->type;
- size += i->dtype->size;
+ size += i->size;
subtypes++;
}
strncat(desc, ")", sizeof(desc) - strlen(desc) - 1);
diff --git a/src/evaluate.c b/src/evaluate.c
index 9cb2376a..8f0acf72 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -604,11 +604,11 @@ static int list_member_evaluate(struct eval_ctx *ctx, struct expr **expr)
static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
{
const struct datatype *dtype = ctx->ectx.dtype, *tmp;
- unsigned int type = dtype ? dtype->type : 0;
+ uint32_t type = dtype ? dtype->type : 0, ntype = 0;
int off = dtype ? dtype->subtypes : 0;
unsigned int flags = EXPR_F_CONSTANT | EXPR_F_SINGLETON;
struct expr *i, *next;
- unsigned int n, len = 0;
+ unsigned int n;
n = 1;
list_for_each_entry_safe(i, next, &(*expr)->expressions, list) {
@@ -624,13 +624,14 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
return -1;
flags &= i->flags;
- len += i->len;
+ ntype <<= TYPE_BITS;
+ ntype |= i->dtype->type;
n++;
}
(*expr)->flags |= flags;
- (*expr)->dtype = concat_type_alloc(*expr);
- (*expr)->len = len;
+ (*expr)->dtype = concat_type_alloc(ntype);
+ (*expr)->len = (*expr)->dtype->size;
if (off > 0)
return expr_error(ctx->msgs, *expr,