diff options
Diffstat (limited to 'src/expr')
40 files changed, 780 insertions, 319 deletions
diff --git a/src/expr/bitwise.c b/src/expr/bitwise.c index d0c7827..e99131a 100644 --- a/src/expr/bitwise.c +++ b/src/expr/bitwise.c @@ -39,31 +39,23 @@ nftnl_expr_bitwise_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_BITWISE_SREG: - memcpy(&bitwise->sreg, data, sizeof(bitwise->sreg)); + memcpy(&bitwise->sreg, data, data_len); break; case NFTNL_EXPR_BITWISE_DREG: - memcpy(&bitwise->dreg, data, sizeof(bitwise->dreg)); + memcpy(&bitwise->dreg, data, data_len); break; case NFTNL_EXPR_BITWISE_OP: - memcpy(&bitwise->op, data, sizeof(bitwise->op)); + memcpy(&bitwise->op, data, data_len); break; case NFTNL_EXPR_BITWISE_LEN: - memcpy(&bitwise->len, data, sizeof(bitwise->len)); + memcpy(&bitwise->len, data, data_len); break; case NFTNL_EXPR_BITWISE_MASK: - memcpy(&bitwise->mask.val, data, data_len); - bitwise->mask.len = data_len; - break; + return nftnl_data_cpy(&bitwise->mask, data, data_len); case NFTNL_EXPR_BITWISE_XOR: - memcpy(&bitwise->xor.val, data, data_len); - bitwise->xor.len = data_len; - break; + return nftnl_data_cpy(&bitwise->xor, data, data_len); case NFTNL_EXPR_BITWISE_DATA: - memcpy(&bitwise->data.val, data, data_len); - bitwise->data.len = data_len; - break; - default: - return -1; + return nftnl_data_cpy(&bitwise->data, data, data_len); } return 0; } @@ -274,13 +266,24 @@ nftnl_expr_bitwise_snprintf(char *buf, size_t size, return err; } +static struct attr_policy bitwise_attr_policy[__NFTNL_EXPR_BITWISE_MAX] = { + [NFTNL_EXPR_BITWISE_SREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_BITWISE_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_BITWISE_LEN] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_BITWISE_MASK] = { .maxlen = NFT_DATA_VALUE_MAXLEN }, + [NFTNL_EXPR_BITWISE_XOR] = { .maxlen = NFT_DATA_VALUE_MAXLEN }, + [NFTNL_EXPR_BITWISE_OP] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_BITWISE_DATA] = { .maxlen = NFT_DATA_VALUE_MAXLEN }, +}; + struct expr_ops expr_ops_bitwise = { .name = "bitwise", .alloc_len = sizeof(struct nftnl_expr_bitwise), - .max_attr = NFTA_BITWISE_MAX, + .nftnl_max_attr = __NFTNL_EXPR_BITWISE_MAX - 1, + .attr_policy = bitwise_attr_policy, .set = nftnl_expr_bitwise_set, .get = nftnl_expr_bitwise_get, .parse = nftnl_expr_bitwise_parse, .build = nftnl_expr_bitwise_build, - .snprintf = nftnl_expr_bitwise_snprintf, + .output = nftnl_expr_bitwise_snprintf, }; diff --git a/src/expr/byteorder.c b/src/expr/byteorder.c index d299745..383e80d 100644 --- a/src/expr/byteorder.c +++ b/src/expr/byteorder.c @@ -37,22 +37,20 @@ nftnl_expr_byteorder_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_BYTEORDER_SREG: - memcpy(&byteorder->sreg, data, sizeof(byteorder->sreg)); + memcpy(&byteorder->sreg, data, data_len); break; case NFTNL_EXPR_BYTEORDER_DREG: - memcpy(&byteorder->dreg, data, sizeof(byteorder->dreg)); + memcpy(&byteorder->dreg, data, data_len); break; case NFTNL_EXPR_BYTEORDER_OP: - memcpy(&byteorder->op, data, sizeof(byteorder->op)); + memcpy(&byteorder->op, data, data_len); break; case NFTNL_EXPR_BYTEORDER_LEN: - memcpy(&byteorder->len, data, sizeof(byteorder->len)); + memcpy(&byteorder->len, data, data_len); break; case NFTNL_EXPR_BYTEORDER_SIZE: - memcpy(&byteorder->size, data, sizeof(byteorder->size)); + memcpy(&byteorder->size, data, data_len); break; - default: - return -1; } return 0; } @@ -212,13 +210,22 @@ nftnl_expr_byteorder_snprintf(char *buf, size_t remain, return offset; } +static struct attr_policy byteorder_attr_policy[__NFTNL_EXPR_BYTEORDER_MAX] = { + [NFTNL_EXPR_BYTEORDER_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_BYTEORDER_SREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_BYTEORDER_OP] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_BYTEORDER_LEN] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_BYTEORDER_SIZE] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_byteorder = { .name = "byteorder", .alloc_len = sizeof(struct nftnl_expr_byteorder), - .max_attr = NFTA_BYTEORDER_MAX, + .nftnl_max_attr = __NFTNL_EXPR_BYTEORDER_MAX - 1, + .attr_policy = byteorder_attr_policy, .set = nftnl_expr_byteorder_set, .get = nftnl_expr_byteorder_get, .parse = nftnl_expr_byteorder_parse, .build = nftnl_expr_byteorder_build, - .snprintf = nftnl_expr_byteorder_snprintf, + .output = nftnl_expr_byteorder_snprintf, }; diff --git a/src/expr/cmp.c b/src/expr/cmp.c index 6030693..d1f0f64 100644 --- a/src/expr/cmp.c +++ b/src/expr/cmp.c @@ -36,17 +36,13 @@ nftnl_expr_cmp_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_CMP_SREG: - memcpy(&cmp->sreg, data, sizeof(cmp->sreg)); + memcpy(&cmp->sreg, data, data_len); break; case NFTNL_EXPR_CMP_OP: - memcpy(&cmp->op, data, sizeof(cmp->op)); + memcpy(&cmp->op, data, data_len); break; case NFTNL_EXPR_CMP_DATA: - memcpy(&cmp->data.val, data, data_len); - cmp->data.len = data_len; - break; - default: - return -1; + return nftnl_data_cpy(&cmp->data, data, data_len); } return 0; } @@ -194,13 +190,20 @@ nftnl_expr_cmp_snprintf(char *buf, size_t remain, return offset; } +static struct attr_policy cmp_attr_policy[__NFTNL_EXPR_CMP_MAX] = { + [NFTNL_EXPR_CMP_SREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_CMP_OP] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_CMP_DATA] = { .maxlen = NFT_DATA_VALUE_MAXLEN } +}; + struct expr_ops expr_ops_cmp = { .name = "cmp", .alloc_len = sizeof(struct nftnl_expr_cmp), - .max_attr = NFTA_CMP_MAX, + .nftnl_max_attr = __NFTNL_EXPR_CMP_MAX - 1, + .attr_policy = cmp_attr_policy, .set = nftnl_expr_cmp_set, .get = nftnl_expr_cmp_get, .parse = nftnl_expr_cmp_parse, .build = nftnl_expr_cmp_build, - .snprintf = nftnl_expr_cmp_snprintf, + .output = nftnl_expr_cmp_snprintf, }; diff --git a/src/expr/connlimit.c b/src/expr/connlimit.c index 3b37587..fcac8bf 100644 --- a/src/expr/connlimit.c +++ b/src/expr/connlimit.c @@ -33,13 +33,11 @@ nftnl_expr_connlimit_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_CONNLIMIT_COUNT: - memcpy(&connlimit->count, data, sizeof(connlimit->count)); + memcpy(&connlimit->count, data, data_len); break; case NFTNL_EXPR_CONNLIMIT_FLAGS: - memcpy(&connlimit->flags, data, sizeof(connlimit->flags)); + memcpy(&connlimit->flags, data, data_len); break; - default: - return -1; } return 0; } @@ -127,13 +125,19 @@ static int nftnl_expr_connlimit_snprintf(char *buf, size_t len, connlimit->count, connlimit->flags); } +static struct attr_policy connlimit_attr_policy[__NFTNL_EXPR_CONNLIMIT_MAX] = { + [NFTNL_EXPR_CONNLIMIT_COUNT] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_CONNLIMIT_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_connlimit = { .name = "connlimit", .alloc_len = sizeof(struct nftnl_expr_connlimit), - .max_attr = NFTA_CONNLIMIT_MAX, + .nftnl_max_attr = __NFTNL_EXPR_CONNLIMIT_MAX - 1, + .attr_policy = connlimit_attr_policy, .set = nftnl_expr_connlimit_set, .get = nftnl_expr_connlimit_get, .parse = nftnl_expr_connlimit_parse, .build = nftnl_expr_connlimit_build, - .snprintf = nftnl_expr_connlimit_snprintf, + .output = nftnl_expr_connlimit_snprintf, }; diff --git a/src/expr/counter.c b/src/expr/counter.c index 1676d70..cef9119 100644 --- a/src/expr/counter.c +++ b/src/expr/counter.c @@ -35,13 +35,11 @@ nftnl_expr_counter_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_CTR_BYTES: - memcpy(&ctr->bytes, data, sizeof(ctr->bytes)); + memcpy(&ctr->bytes, data, data_len); break; case NFTNL_EXPR_CTR_PACKETS: - memcpy(&ctr->pkts, data, sizeof(ctr->pkts)); + memcpy(&ctr->pkts, data, data_len); break; - default: - return -1; } return 0; } @@ -125,13 +123,19 @@ static int nftnl_expr_counter_snprintf(char *buf, size_t len, ctr->pkts, ctr->bytes); } +static struct attr_policy counter_attr_policy[__NFTNL_EXPR_CTR_MAX] = { + [NFTNL_EXPR_CTR_PACKETS] = { .maxlen = sizeof(uint64_t) }, + [NFTNL_EXPR_CTR_BYTES] = { .maxlen = sizeof(uint64_t) }, +}; + struct expr_ops expr_ops_counter = { .name = "counter", .alloc_len = sizeof(struct nftnl_expr_counter), - .max_attr = NFTA_COUNTER_MAX, + .nftnl_max_attr = __NFTNL_EXPR_CTR_MAX - 1, + .attr_policy = counter_attr_policy, .set = nftnl_expr_counter_set, .get = nftnl_expr_counter_get, .parse = nftnl_expr_counter_parse, .build = nftnl_expr_counter_build, - .snprintf = nftnl_expr_counter_snprintf, + .output = nftnl_expr_counter_snprintf, }; diff --git a/src/expr/ct.c b/src/expr/ct.c index d5dfc81..bea0522 100644 --- a/src/expr/ct.c +++ b/src/expr/ct.c @@ -39,19 +39,17 @@ nftnl_expr_ct_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_CT_KEY: - memcpy(&ct->key, data, sizeof(ct->key)); + memcpy(&ct->key, data, data_len); break; case NFTNL_EXPR_CT_DIR: - memcpy(&ct->dir, data, sizeof(ct->dir)); + memcpy(&ct->dir, data, data_len); break; case NFTNL_EXPR_CT_DREG: - memcpy(&ct->dreg, data, sizeof(ct->dreg)); + memcpy(&ct->dreg, data, data_len); break; case NFTNL_EXPR_CT_SREG: - memcpy(&ct->sreg, data, sizeof(ct->sreg)); + memcpy(&ct->sreg, data, data_len); break; - default: - return -1; } return 0; } @@ -250,13 +248,21 @@ nftnl_expr_ct_snprintf(char *buf, size_t remain, return offset; } +static struct attr_policy ct_attr_policy[__NFTNL_EXPR_CT_MAX] = { + [NFTNL_EXPR_CT_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_CT_KEY] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_CT_DIR] = { .maxlen = sizeof(uint8_t) }, + [NFTNL_EXPR_CT_SREG] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_ct = { .name = "ct", .alloc_len = sizeof(struct nftnl_expr_ct), - .max_attr = NFTA_CT_MAX, + .nftnl_max_attr = __NFTNL_EXPR_CT_MAX - 1, + .attr_policy = ct_attr_policy, .set = nftnl_expr_ct_set, .get = nftnl_expr_ct_get, .parse = nftnl_expr_ct_parse, .build = nftnl_expr_ct_build, - .snprintf = nftnl_expr_ct_snprintf, + .output = nftnl_expr_ct_snprintf, }; diff --git a/src/expr/data_reg.c b/src/expr/data_reg.c index 2633a77..d2ccf2e 100644 --- a/src/expr/data_reg.c +++ b/src/expr/data_reg.c @@ -206,14 +206,16 @@ int nftnl_parse_data(union nftnl_data_reg *data, struct nlattr *attr, int *type) return ret; } -void nftnl_free_verdict(const union nftnl_data_reg *data) +int nftnl_data_cpy(union nftnl_data_reg *dreg, const void *src, uint32_t len) { - switch(data->verdict) { - case NFT_JUMP: - case NFT_GOTO: - xfree(data->chain); - break; - default: - break; + int ret = 0; + + if (len > sizeof(dreg->val)) { + len = sizeof(dreg->val); + ret = -1; } + + memcpy(dreg->val, src, len); + dreg->len = len; + return ret; } diff --git a/src/expr/dup.c b/src/expr/dup.c index f041b55..28d686b 100644 --- a/src/expr/dup.c +++ b/src/expr/dup.c @@ -32,13 +32,11 @@ static int nftnl_expr_dup_set(struct nftnl_expr *e, uint16_t type, switch (type) { case NFTNL_EXPR_DUP_SREG_ADDR: - memcpy(&dup->sreg_addr, data, sizeof(dup->sreg_addr)); + memcpy(&dup->sreg_addr, data, data_len); break; case NFTNL_EXPR_DUP_SREG_DEV: - memcpy(&dup->sreg_dev, data, sizeof(dup->sreg_dev)); + memcpy(&dup->sreg_dev, data, data_len); break; - default: - return -1; } return 0; } @@ -130,13 +128,19 @@ static int nftnl_expr_dup_snprintf(char *buf, size_t remain, return offset; } +static struct attr_policy dup_attr_policy[__NFTNL_EXPR_DUP_MAX] = { + [NFTNL_EXPR_DUP_SREG_ADDR] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_DUP_SREG_DEV] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_dup = { .name = "dup", .alloc_len = sizeof(struct nftnl_expr_dup), - .max_attr = NFTA_DUP_MAX, + .nftnl_max_attr = __NFTNL_EXPR_DUP_MAX - 1, + .attr_policy = dup_attr_policy, .set = nftnl_expr_dup_set, .get = nftnl_expr_dup_get, .parse = nftnl_expr_dup_parse, .build = nftnl_expr_dup_build, - .snprintf = nftnl_expr_dup_snprintf, + .output = nftnl_expr_dup_snprintf, }; diff --git a/src/expr/dynset.c b/src/expr/dynset.c index 85d64bb..8a159f8 100644 --- a/src/expr/dynset.c +++ b/src/expr/dynset.c @@ -41,16 +41,16 @@ nftnl_expr_dynset_set(struct nftnl_expr *e, uint16_t type, switch (type) { case NFTNL_EXPR_DYNSET_SREG_KEY: - memcpy(&dynset->sreg_key, data, sizeof(dynset->sreg_key)); + memcpy(&dynset->sreg_key, data, data_len); break; case NFTNL_EXPR_DYNSET_SREG_DATA: - memcpy(&dynset->sreg_data, data, sizeof(dynset->sreg_data)); + memcpy(&dynset->sreg_data, data, data_len); break; case NFTNL_EXPR_DYNSET_OP: - memcpy(&dynset->op, data, sizeof(dynset->op)); + memcpy(&dynset->op, data, data_len); break; case NFTNL_EXPR_DYNSET_TIMEOUT: - memcpy(&dynset->timeout, data, sizeof(dynset->timeout)); + memcpy(&dynset->timeout, data, data_len); break; case NFTNL_EXPR_DYNSET_SET_NAME: dynset->set_name = strdup((const char *)data); @@ -58,7 +58,7 @@ nftnl_expr_dynset_set(struct nftnl_expr *e, uint16_t type, return -1; break; case NFTNL_EXPR_DYNSET_SET_ID: - memcpy(&dynset->set_id, data, sizeof(dynset->set_id)); + memcpy(&dynset->set_id, data, data_len); break; case NFTNL_EXPR_DYNSET_EXPR: list_for_each_entry_safe(expr, next, &dynset->expr_list, head) @@ -68,7 +68,7 @@ nftnl_expr_dynset_set(struct nftnl_expr *e, uint16_t type, list_add(&expr->head, &dynset->expr_list); break; case NFTNL_EXPR_DYNSET_FLAGS: - memcpy(&dynset->dynset_flags, data, sizeof(dynset->dynset_flags)); + memcpy(&dynset->dynset_flags, data, data_len); break; default: return -1; @@ -363,15 +363,28 @@ static void nftnl_expr_dynset_free(const struct nftnl_expr *e) nftnl_expr_free(expr); } +static struct attr_policy dynset_attr_policy[__NFTNL_EXPR_DYNSET_MAX] = { + [NFTNL_EXPR_DYNSET_SREG_KEY] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_DYNSET_SREG_DATA] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_DYNSET_OP] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_DYNSET_TIMEOUT] = { .maxlen = sizeof(uint64_t) }, + [NFTNL_EXPR_DYNSET_SET_NAME] = { .maxlen = NFT_SET_MAXNAMELEN }, + [NFTNL_EXPR_DYNSET_SET_ID] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_DYNSET_EXPR] = { .maxlen = 0 }, + [NFTNL_EXPR_DYNSET_EXPRESSIONS] = { .maxlen = 0 }, + [NFTNL_EXPR_DYNSET_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_dynset = { .name = "dynset", .alloc_len = sizeof(struct nftnl_expr_dynset), - .max_attr = NFTA_DYNSET_MAX, + .nftnl_max_attr = __NFTNL_EXPR_DYNSET_MAX - 1, + .attr_policy = dynset_attr_policy, .init = nftnl_expr_dynset_init, .free = nftnl_expr_dynset_free, .set = nftnl_expr_dynset_set, .get = nftnl_expr_dynset_get, .parse = nftnl_expr_dynset_parse, .build = nftnl_expr_dynset_build, - .snprintf = nftnl_expr_dynset_snprintf, + .output = nftnl_expr_dynset_snprintf, }; diff --git a/src/expr/exthdr.c b/src/expr/exthdr.c index 1b813b1..453902c 100644 --- a/src/expr/exthdr.c +++ b/src/expr/exthdr.c @@ -46,28 +46,26 @@ nftnl_expr_exthdr_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_EXTHDR_DREG: - memcpy(&exthdr->dreg, data, sizeof(exthdr->dreg)); + memcpy(&exthdr->dreg, data, data_len); break; case NFTNL_EXPR_EXTHDR_TYPE: - memcpy(&exthdr->type, data, sizeof(exthdr->type)); + memcpy(&exthdr->type, data, data_len); break; case NFTNL_EXPR_EXTHDR_OFFSET: - memcpy(&exthdr->offset, data, sizeof(exthdr->offset)); + memcpy(&exthdr->offset, data, data_len); break; case NFTNL_EXPR_EXTHDR_LEN: - memcpy(&exthdr->len, data, sizeof(exthdr->len)); + memcpy(&exthdr->len, data, data_len); break; case NFTNL_EXPR_EXTHDR_OP: - memcpy(&exthdr->op, data, sizeof(exthdr->op)); + memcpy(&exthdr->op, data, data_len); break; case NFTNL_EXPR_EXTHDR_FLAGS: - memcpy(&exthdr->flags, data, sizeof(exthdr->flags)); + memcpy(&exthdr->flags, data, data_len); break; case NFTNL_EXPR_EXTHDR_SREG: - memcpy(&exthdr->sreg, data, sizeof(exthdr->sreg)); + memcpy(&exthdr->sreg, data, data_len); break; - default: - return -1; } return 0; } @@ -247,20 +245,36 @@ nftnl_expr_exthdr_snprintf(char *buf, size_t len, exthdr->offset, exthdr->flags & NFT_EXTHDR_F_PRESENT ? " present" : "", exthdr->dreg); - else + else if (e->flags & (1 << NFTNL_EXPR_EXTHDR_SREG)) return snprintf(buf, len, "write%s reg %u => %ub @ %u + %u ", op2str(exthdr->op), exthdr->sreg, exthdr->len, exthdr->type, exthdr->offset); + else if (exthdr->op == NFT_EXTHDR_OP_TCPOPT && exthdr->len == 0) + return snprintf(buf, len, "reset tcpopt %u ", exthdr->type); + else + return snprintf(buf, len, "op %u len %u type %u offset %u ", + exthdr->op, exthdr->len, exthdr->type, exthdr->offset); } +static struct attr_policy exthdr_attr_policy[__NFTNL_EXPR_EXTHDR_MAX] = { + [NFTNL_EXPR_EXTHDR_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_EXTHDR_TYPE] = { .maxlen = sizeof(uint8_t) }, + [NFTNL_EXPR_EXTHDR_OFFSET] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_EXTHDR_LEN] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_EXTHDR_FLAGS] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_EXTHDR_OP] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_EXTHDR_SREG] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_exthdr = { .name = "exthdr", .alloc_len = sizeof(struct nftnl_expr_exthdr), - .max_attr = NFTA_EXTHDR_MAX, + .nftnl_max_attr = __NFTNL_EXPR_EXTHDR_MAX - 1, + .attr_policy = exthdr_attr_policy, .set = nftnl_expr_exthdr_set, .get = nftnl_expr_exthdr_get, .parse = nftnl_expr_exthdr_parse, .build = nftnl_expr_exthdr_build, - .snprintf = nftnl_expr_exthdr_snprintf, + .output = nftnl_expr_exthdr_snprintf, }; diff --git a/src/expr/fib.c b/src/expr/fib.c index aaff52a..20bc125 100644 --- a/src/expr/fib.c +++ b/src/expr/fib.c @@ -35,16 +35,14 @@ nftnl_expr_fib_set(struct nftnl_expr *e, uint16_t result, switch (result) { case NFTNL_EXPR_FIB_RESULT: - memcpy(&fib->result, data, sizeof(fib->result)); + memcpy(&fib->result, data, data_len); break; case NFTNL_EXPR_FIB_DREG: - memcpy(&fib->dreg, data, sizeof(fib->dreg)); + memcpy(&fib->dreg, data, data_len); break; case NFTNL_EXPR_FIB_FLAGS: - memcpy(&fib->flags, data, sizeof(fib->flags)); + memcpy(&fib->flags, data, data_len); break; - default: - return -1; } return 0; } @@ -190,13 +188,20 @@ nftnl_expr_fib_snprintf(char *buf, size_t remain, return offset; } +static struct attr_policy fib_attr_policy[__NFTNL_EXPR_FIB_MAX] = { + [NFTNL_EXPR_FIB_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_FIB_RESULT] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_FIB_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_fib = { .name = "fib", .alloc_len = sizeof(struct nftnl_expr_fib), - .max_attr = NFTA_FIB_MAX, + .nftnl_max_attr = __NFTNL_EXPR_FIB_MAX - 1, + .attr_policy = fib_attr_policy, .set = nftnl_expr_fib_set, .get = nftnl_expr_fib_get, .parse = nftnl_expr_fib_parse, .build = nftnl_expr_fib_build, - .snprintf = nftnl_expr_fib_snprintf, + .output = nftnl_expr_fib_snprintf, }; diff --git a/src/expr/flow_offload.c b/src/expr/flow_offload.c index a826202..5f209a6 100644 --- a/src/expr/flow_offload.c +++ b/src/expr/flow_offload.c @@ -25,8 +25,6 @@ static int nftnl_expr_flow_set(struct nftnl_expr *e, uint16_t type, if (!flow->table_name) return -1; break; - default: - return -1; } return 0; } @@ -111,14 +109,19 @@ static void nftnl_expr_flow_free(const struct nftnl_expr *e) xfree(flow->table_name); } +static struct attr_policy flow_offload_attr_policy[__NFTNL_EXPR_FLOW_MAX] = { + [NFTNL_EXPR_FLOW_TABLE_NAME] = { .maxlen = NFT_NAME_MAXLEN }, +}; + struct expr_ops expr_ops_flow = { .name = "flow_offload", .alloc_len = sizeof(struct nftnl_expr_flow), - .max_attr = NFTA_FLOW_MAX, + .nftnl_max_attr = __NFTNL_EXPR_FLOW_MAX - 1, + .attr_policy = flow_offload_attr_policy, .free = nftnl_expr_flow_free, .set = nftnl_expr_flow_set, .get = nftnl_expr_flow_get, .parse = nftnl_expr_flow_parse, .build = nftnl_expr_flow_build, - .snprintf = nftnl_expr_flow_snprintf, + .output = nftnl_expr_flow_snprintf, }; diff --git a/src/expr/fwd.c b/src/expr/fwd.c index 82e5a41..04cb089 100644 --- a/src/expr/fwd.c +++ b/src/expr/fwd.c @@ -33,16 +33,14 @@ static int nftnl_expr_fwd_set(struct nftnl_expr *e, uint16_t type, switch (type) { case NFTNL_EXPR_FWD_SREG_DEV: - memcpy(&fwd->sreg_dev, data, sizeof(fwd->sreg_dev)); + memcpy(&fwd->sreg_dev, data, data_len); break; case NFTNL_EXPR_FWD_SREG_ADDR: - memcpy(&fwd->sreg_addr, data, sizeof(fwd->sreg_addr)); + memcpy(&fwd->sreg_addr, data, data_len); break; case NFTNL_EXPR_FWD_NFPROTO: - memcpy(&fwd->nfproto, data, sizeof(fwd->nfproto)); + memcpy(&fwd->nfproto, data, data_len); break; - default: - return -1; } return 0; } @@ -150,13 +148,20 @@ static int nftnl_expr_fwd_snprintf(char *buf, size_t remain, return offset; } +static struct attr_policy fwd_attr_policy[__NFTNL_EXPR_FWD_MAX] = { + [NFTNL_EXPR_FWD_SREG_DEV] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_FWD_SREG_ADDR] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_FWD_NFPROTO] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_fwd = { .name = "fwd", .alloc_len = sizeof(struct nftnl_expr_fwd), - .max_attr = NFTA_FWD_MAX, + .nftnl_max_attr = __NFTNL_EXPR_FWD_MAX - 1, + .attr_policy = fwd_attr_policy, .set = nftnl_expr_fwd_set, .get = nftnl_expr_fwd_get, .parse = nftnl_expr_fwd_parse, .build = nftnl_expr_fwd_build, - .snprintf = nftnl_expr_fwd_snprintf, + .output = nftnl_expr_fwd_snprintf, }; diff --git a/src/expr/hash.c b/src/expr/hash.c index 10b4a72..eb44b2e 100644 --- a/src/expr/hash.c +++ b/src/expr/hash.c @@ -37,25 +37,25 @@ nftnl_expr_hash_set(struct nftnl_expr *e, uint16_t type, struct nftnl_expr_hash *hash = nftnl_expr_data(e); switch (type) { case NFTNL_EXPR_HASH_SREG: - memcpy(&hash->sreg, data, sizeof(hash->sreg)); + memcpy(&hash->sreg, data, data_len); break; case NFTNL_EXPR_HASH_DREG: - memcpy(&hash->dreg, data, sizeof(hash->dreg)); + memcpy(&hash->dreg, data, data_len); break; case NFTNL_EXPR_HASH_LEN: - memcpy(&hash->len, data, sizeof(hash->len)); + memcpy(&hash->len, data, data_len); break; case NFTNL_EXPR_HASH_MODULUS: - memcpy(&hash->modulus, data, sizeof(hash->modulus)); + memcpy(&hash->modulus, data, data_len); break; case NFTNL_EXPR_HASH_SEED: - memcpy(&hash->seed, data, sizeof(hash->seed)); + memcpy(&hash->seed, data, data_len); break; case NFTNL_EXPR_HASH_OFFSET: - memcpy(&hash->offset, data, sizeof(hash->offset)); + memcpy(&hash->offset, data, data_len); break; case NFTNL_EXPR_HASH_TYPE: - memcpy(&hash->type, data, sizeof(hash->type)); + memcpy(&hash->type, data, data_len); break; default: return -1; @@ -218,13 +218,24 @@ nftnl_expr_hash_snprintf(char *buf, size_t remain, return offset; } +static struct attr_policy hash_attr_policy[__NFTNL_EXPR_HASH_MAX] = { + [NFTNL_EXPR_HASH_SREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_HASH_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_HASH_LEN] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_HASH_MODULUS] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_HASH_SEED] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_HASH_OFFSET] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_HASH_TYPE] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_hash = { .name = "hash", .alloc_len = sizeof(struct nftnl_expr_hash), - .max_attr = NFTA_HASH_MAX, + .nftnl_max_attr = __NFTNL_EXPR_HASH_MAX - 1, + .attr_policy = hash_attr_policy, .set = nftnl_expr_hash_set, .get = nftnl_expr_hash_get, .parse = nftnl_expr_hash_parse, .build = nftnl_expr_hash_build, - .snprintf = nftnl_expr_hash_snprintf, + .output = nftnl_expr_hash_snprintf, }; diff --git a/src/expr/immediate.c b/src/expr/immediate.c index 94b043c..ab1276a 100644 --- a/src/expr/immediate.c +++ b/src/expr/immediate.c @@ -33,14 +33,12 @@ nftnl_expr_immediate_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_IMM_DREG: - memcpy(&imm->dreg, data, sizeof(imm->dreg)); + memcpy(&imm->dreg, data, data_len); break; case NFTNL_EXPR_IMM_DATA: - memcpy(&imm->data.val, data, data_len); - imm->data.len = data_len; - break; + return nftnl_data_cpy(&imm->data, data, data_len); case NFTNL_EXPR_IMM_VERDICT: - memcpy(&imm->data.verdict, data, sizeof(imm->data.verdict)); + memcpy(&imm->data.verdict, data, data_len); break; case NFTNL_EXPR_IMM_CHAIN: if (e->flags & (1 << NFTNL_EXPR_IMM_CHAIN)) @@ -51,10 +49,8 @@ nftnl_expr_immediate_set(struct nftnl_expr *e, uint16_t type, return -1; break; case NFTNL_EXPR_IMM_CHAIN_ID: - memcpy(&imm->data.chain_id, data, sizeof(uint32_t)); + memcpy(&imm->data.chain_id, data, data_len); break; - default: - return -1; } return 0; } @@ -216,18 +212,27 @@ static void nftnl_expr_immediate_free(const struct nftnl_expr *e) { struct nftnl_expr_immediate *imm = nftnl_expr_data(e); - if (e->flags & (1 << NFTNL_EXPR_IMM_VERDICT)) - nftnl_free_verdict(&imm->data); + if (e->flags & (1 << NFTNL_EXPR_IMM_CHAIN)) + xfree(imm->data.chain); } +static struct attr_policy immediate_attr_policy[__NFTNL_EXPR_IMM_MAX] = { + [NFTNL_EXPR_IMM_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_IMM_DATA] = { .maxlen = NFT_DATA_VALUE_MAXLEN }, + [NFTNL_EXPR_IMM_VERDICT] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_IMM_CHAIN] = { .maxlen = NFT_CHAIN_MAXNAMELEN }, + [NFTNL_EXPR_IMM_CHAIN_ID] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_immediate = { .name = "immediate", .alloc_len = sizeof(struct nftnl_expr_immediate), - .max_attr = NFTA_IMMEDIATE_MAX, + .nftnl_max_attr = __NFTNL_EXPR_IMM_MAX - 1, + .attr_policy = immediate_attr_policy, .free = nftnl_expr_immediate_free, .set = nftnl_expr_immediate_set, .get = nftnl_expr_immediate_get, .parse = nftnl_expr_immediate_parse, .build = nftnl_expr_immediate_build, - .snprintf = nftnl_expr_immediate_snprintf, + .output = nftnl_expr_immediate_snprintf, }; diff --git a/src/expr/inner.c b/src/expr/inner.c new file mode 100644 index 0000000..4f66e94 --- /dev/null +++ b/src/expr/inner.c @@ -0,0 +1,220 @@ +/* + * (C) 2012-2022 by Pablo Neira Ayuso <pablo@netfilter.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include "internal.h" + +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <limits.h> +#include <arpa/inet.h> +#include <errno.h> +#include <libmnl/libmnl.h> + +#include <linux/netfilter/nf_tables.h> + +#include <libnftnl/expr.h> +#include <libnftnl/rule.h> + +struct nftnl_expr_inner { + uint32_t type; + uint32_t flags; + uint32_t hdrsize; + struct nftnl_expr *expr; +}; + +static void nftnl_expr_inner_free(const struct nftnl_expr *e) +{ + struct nftnl_expr_inner *inner = nftnl_expr_data(e); + + if (inner->expr) + nftnl_expr_free(inner->expr); +} + +static int +nftnl_expr_inner_set(struct nftnl_expr *e, uint16_t type, + const void *data, uint32_t data_len) +{ + struct nftnl_expr_inner *inner = nftnl_expr_data(e); + + switch(type) { + case NFTNL_EXPR_INNER_TYPE: + memcpy(&inner->type, data, data_len); + break; + case NFTNL_EXPR_INNER_FLAGS: + memcpy(&inner->flags, data, data_len); + break; + case NFTNL_EXPR_INNER_HDRSIZE: + memcpy(&inner->hdrsize, data, data_len); + break; + case NFTNL_EXPR_INNER_EXPR: + if (inner->expr) + nftnl_expr_free(inner->expr); + + inner->expr = (void *)data; + break; + } + return 0; +} + +static const void * +nftnl_expr_inner_get(const struct nftnl_expr *e, uint16_t type, + uint32_t *data_len) +{ + struct nftnl_expr_inner *inner = nftnl_expr_data(e); + + switch(type) { + case NFTNL_EXPR_INNER_FLAGS: + *data_len = sizeof(inner->flags); + return &inner->flags; + case NFTNL_EXPR_INNER_TYPE: + *data_len = sizeof(inner->type); + return &inner->type; + case NFTNL_EXPR_INNER_HDRSIZE: + *data_len = sizeof(inner->hdrsize); + return &inner->hdrsize; + case NFTNL_EXPR_INNER_EXPR: + return inner->expr; + } + return NULL; +} + +static void +nftnl_expr_inner_build(struct nlmsghdr *nlh, const struct nftnl_expr *e) +{ + struct nftnl_expr_inner *inner = nftnl_expr_data(e); + struct nlattr *nest; + + mnl_attr_put_u32(nlh, NFTA_INNER_NUM, htonl(0)); + if (e->flags & (1 << NFTNL_EXPR_INNER_TYPE)) + mnl_attr_put_u32(nlh, NFTA_INNER_TYPE, htonl(inner->type)); + if (e->flags & (1 << NFTNL_EXPR_INNER_FLAGS)) + mnl_attr_put_u32(nlh, NFTA_INNER_FLAGS, htonl(inner->flags)); + if (e->flags & (1 << NFTNL_EXPR_INNER_HDRSIZE)) + mnl_attr_put_u32(nlh, NFTA_INNER_HDRSIZE, htonl(inner->hdrsize)); + if (e->flags & (1 << NFTNL_EXPR_INNER_EXPR)) { + nest = mnl_attr_nest_start(nlh, NFTA_INNER_EXPR); + nftnl_expr_build_payload(nlh, inner->expr); + mnl_attr_nest_end(nlh, nest); + } +} + +static int nftnl_inner_parse_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = data; + int type = mnl_attr_get_type(attr); + + if (mnl_attr_type_valid(attr, NFTA_INNER_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case NFTA_INNER_NUM: + case NFTA_INNER_TYPE: + case NFTA_INNER_HDRSIZE: + case NFTA_INNER_FLAGS: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) + abi_breakage(); + break; + case NFTA_INNER_EXPR: + if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) + abi_breakage(); + break; + } + + tb[type] = attr; + + return MNL_CB_OK; +} + +static int +nftnl_expr_inner_parse(struct nftnl_expr *e, struct nlattr *attr) +{ + struct nftnl_expr_inner *inner = nftnl_expr_data(e); + struct nlattr *tb[NFTA_INNER_MAX + 1] = {}; + struct nftnl_expr *expr; + int err; + + err = mnl_attr_parse_nested(attr, nftnl_inner_parse_cb, tb); + if (err < 0) + return err; + + if (tb[NFTA_INNER_HDRSIZE]) { + inner->hdrsize = + ntohl(mnl_attr_get_u32(tb[NFTA_INNER_HDRSIZE])); + e->flags |= (1 << NFTNL_EXPR_INNER_HDRSIZE); + } + if (tb[NFTA_INNER_FLAGS]) { + inner->flags = + ntohl(mnl_attr_get_u32(tb[NFTA_INNER_FLAGS])); + e->flags |= (1 << NFTNL_EXPR_INNER_FLAGS); + } + if (tb[NFTA_INNER_TYPE]) { + inner->type = + ntohl(mnl_attr_get_u32(tb[NFTA_INNER_TYPE])); + e->flags |= (1 << NFTNL_EXPR_INNER_TYPE); + } + if (tb[NFTA_INNER_EXPR]) { + expr = nftnl_expr_parse(tb[NFTA_INNER_EXPR]); + if (!expr) + return -1; + + if (inner->expr) + nftnl_expr_free(inner->expr); + + inner->expr = expr; + e->flags |= (1 << NFTNL_EXPR_INNER_EXPR); + } + + return 0; +} + +static int +nftnl_expr_inner_snprintf(char *buf, size_t remain, uint32_t flags, + const struct nftnl_expr *e) +{ + struct nftnl_expr_inner *inner = nftnl_expr_data(e); + uint32_t offset = 0; + int ret; + + ret = snprintf(buf, remain, "type %u hdrsize %u flags %x [", + inner->type, inner->hdrsize, inner->flags); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + + ret = snprintf(buf + offset, remain, " %s ", inner->expr->ops->name); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + + ret = nftnl_expr_snprintf(buf + offset, remain, inner->expr, + NFTNL_OUTPUT_DEFAULT, 0); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + + ret = snprintf(buf + offset, remain, "] "); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + + return offset; +} + +static struct attr_policy inner_attr_policy[__NFTNL_EXPR_INNER_MAX] = { + [NFTNL_EXPR_INNER_TYPE] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_INNER_FLAGS] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_INNER_HDRSIZE] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_INNER_EXPR] = { .maxlen = 0 }, +}; + +struct expr_ops expr_ops_inner = { + .name = "inner", + .alloc_len = sizeof(struct nftnl_expr_inner), + .nftnl_max_attr = __NFTNL_EXPR_INNER_MAX - 1, + .attr_policy = inner_attr_policy, + .free = nftnl_expr_inner_free, + .set = nftnl_expr_inner_set, + .get = nftnl_expr_inner_get, + .parse = nftnl_expr_inner_parse, + .build = nftnl_expr_inner_build, + .output = nftnl_expr_inner_snprintf, +}; diff --git a/src/expr/last.c b/src/expr/last.c index 0020fbc..8e5b88e 100644 --- a/src/expr/last.c +++ b/src/expr/last.c @@ -22,6 +22,7 @@ struct nftnl_expr_last { uint64_t msecs; + uint32_t set; }; static int nftnl_expr_last_set(struct nftnl_expr *e, uint16_t type, @@ -31,10 +32,11 @@ static int nftnl_expr_last_set(struct nftnl_expr *e, uint16_t type, switch (type) { case NFTNL_EXPR_LAST_MSECS: - memcpy(&last->msecs, data, sizeof(last->msecs)); + memcpy(&last->msecs, data, data_len); + break; + case NFTNL_EXPR_LAST_SET: + memcpy(&last->set, data, data_len); break; - default: - return -1; } return 0; } @@ -48,6 +50,9 @@ static const void *nftnl_expr_last_get(const struct nftnl_expr *e, case NFTNL_EXPR_LAST_MSECS: *data_len = sizeof(last->msecs); return &last->msecs; + case NFTNL_EXPR_LAST_SET: + *data_len = sizeof(last->set); + return &last->set; } return NULL; } @@ -65,6 +70,10 @@ static int nftnl_expr_last_cb(const struct nlattr *attr, void *data) if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0) abi_breakage(); break; + case NFTA_LAST_SET: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) + abi_breakage(); + break; } tb[type] = attr; @@ -78,6 +87,8 @@ nftnl_expr_last_build(struct nlmsghdr *nlh, const struct nftnl_expr *e) if (e->flags & (1 << NFTNL_EXPR_LAST_MSECS)) mnl_attr_put_u64(nlh, NFTA_LAST_MSECS, htobe64(last->msecs)); + if (e->flags & (1 << NFTNL_EXPR_LAST_SET)) + mnl_attr_put_u32(nlh, NFTA_LAST_SET, htonl(last->set)); } static int @@ -93,6 +104,10 @@ nftnl_expr_last_parse(struct nftnl_expr *e, struct nlattr *attr) last->msecs = be64toh(mnl_attr_get_u64(tb[NFTA_LAST_MSECS])); e->flags |= (1 << NFTNL_EXPR_LAST_MSECS); } + if (tb[NFTA_LAST_SET]) { + last->set = ntohl(mnl_attr_get_u32(tb[NFTA_LAST_SET])); + e->flags |= (1 << NFTNL_EXPR_LAST_SET); + } return 0; } @@ -103,16 +118,25 @@ static int nftnl_expr_last_snprintf(char *buf, size_t len, { struct nftnl_expr_last *last = nftnl_expr_data(e); - return snprintf(buf, len, "last %"PRIu64" ", last->msecs); + if (!last->set) + return snprintf(buf, len, "never "); + + return snprintf(buf, len, "%"PRIu64" ", last->msecs); } +static struct attr_policy last_attr_policy[__NFTNL_EXPR_LAST_MAX] = { + [NFTNL_EXPR_LAST_MSECS] = { .maxlen = sizeof(uint64_t) }, + [NFTNL_EXPR_LAST_SET] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_last = { .name = "last", .alloc_len = sizeof(struct nftnl_expr_last), - .max_attr = NFTA_LAST_MAX, + .nftnl_max_attr = __NFTNL_EXPR_LAST_MAX - 1, + .attr_policy = last_attr_policy, .set = nftnl_expr_last_set, .get = nftnl_expr_last_get, .parse = nftnl_expr_last_parse, .build = nftnl_expr_last_build, - .snprintf = nftnl_expr_last_snprintf, + .output = nftnl_expr_last_snprintf, }; diff --git a/src/expr/limit.c b/src/expr/limit.c index 3dfd54a..9d02592 100644 --- a/src/expr/limit.c +++ b/src/expr/limit.c @@ -38,22 +38,20 @@ nftnl_expr_limit_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_LIMIT_RATE: - memcpy(&limit->rate, data, sizeof(limit->rate)); + memcpy(&limit->rate, data, data_len); break; case NFTNL_EXPR_LIMIT_UNIT: - memcpy(&limit->unit, data, sizeof(limit->unit)); + memcpy(&limit->unit, data, data_len); break; case NFTNL_EXPR_LIMIT_BURST: - memcpy(&limit->burst, data, sizeof(limit->burst)); + memcpy(&limit->burst, data, data_len); break; case NFTNL_EXPR_LIMIT_TYPE: - memcpy(&limit->type, data, sizeof(limit->type)); + memcpy(&limit->type, data, data_len); break; case NFTNL_EXPR_LIMIT_FLAGS: - memcpy(&limit->flags, data, sizeof(limit->flags)); + memcpy(&limit->flags, data, data_len); break; - default: - return -1; } return 0; } @@ -194,13 +192,22 @@ nftnl_expr_limit_snprintf(char *buf, size_t len, limit_to_type(limit->type), limit->flags); } +static struct attr_policy limit_attr_policy[__NFTNL_EXPR_LIMIT_MAX] = { + [NFTNL_EXPR_LIMIT_RATE] = { .maxlen = sizeof(uint64_t) }, + [NFTNL_EXPR_LIMIT_UNIT] = { .maxlen = sizeof(uint64_t) }, + [NFTNL_EXPR_LIMIT_BURST] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_LIMIT_TYPE] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_LIMIT_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_limit = { .name = "limit", .alloc_len = sizeof(struct nftnl_expr_limit), - .max_attr = NFTA_LIMIT_MAX, + .nftnl_max_attr = __NFTNL_EXPR_LIMIT_MAX - 1, + .attr_policy = limit_attr_policy, .set = nftnl_expr_limit_set, .get = nftnl_expr_limit_get, .parse = nftnl_expr_limit_parse, .build = nftnl_expr_limit_build, - .snprintf = nftnl_expr_limit_snprintf, + .output = nftnl_expr_limit_snprintf, }; diff --git a/src/expr/log.c b/src/expr/log.c index 86db548..18ec2b6 100644 --- a/src/expr/log.c +++ b/src/expr/log.c @@ -46,22 +46,20 @@ static int nftnl_expr_log_set(struct nftnl_expr *e, uint16_t type, return -1; break; case NFTNL_EXPR_LOG_GROUP: - memcpy(&log->group, data, sizeof(log->group)); + memcpy(&log->group, data, data_len); break; case NFTNL_EXPR_LOG_SNAPLEN: - memcpy(&log->snaplen, data, sizeof(log->snaplen)); + memcpy(&log->snaplen, data, data_len); break; case NFTNL_EXPR_LOG_QTHRESHOLD: - memcpy(&log->qthreshold, data, sizeof(log->qthreshold)); + memcpy(&log->qthreshold, data, data_len); break; case NFTNL_EXPR_LOG_LEVEL: - memcpy(&log->level, data, sizeof(log->level)); + memcpy(&log->level, data, data_len); break; case NFTNL_EXPR_LOG_FLAGS: - memcpy(&log->flags, data, sizeof(log->flags)); + memcpy(&log->flags, data, data_len); break; - default: - return -1; } return 0; } @@ -244,14 +242,24 @@ static void nftnl_expr_log_free(const struct nftnl_expr *e) xfree(log->prefix); } +static struct attr_policy log_attr_policy[__NFTNL_EXPR_LOG_MAX] = { + [NFTNL_EXPR_LOG_PREFIX] = { .maxlen = NF_LOG_PREFIXLEN }, + [NFTNL_EXPR_LOG_GROUP] = { .maxlen = sizeof(uint16_t) }, + [NFTNL_EXPR_LOG_SNAPLEN] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_LOG_QTHRESHOLD] = { .maxlen = sizeof(uint16_t) }, + [NFTNL_EXPR_LOG_LEVEL] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_LOG_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_log = { .name = "log", .alloc_len = sizeof(struct nftnl_expr_log), - .max_attr = NFTA_LOG_MAX, + .nftnl_max_attr = __NFTNL_EXPR_LOG_MAX - 1, + .attr_policy = log_attr_policy, .free = nftnl_expr_log_free, .set = nftnl_expr_log_set, .get = nftnl_expr_log_get, .parse = nftnl_expr_log_parse, .build = nftnl_expr_log_build, - .snprintf = nftnl_expr_log_snprintf, + .output = nftnl_expr_log_snprintf, }; diff --git a/src/expr/lookup.c b/src/expr/lookup.c index 83adce9..21a7fce 100644 --- a/src/expr/lookup.c +++ b/src/expr/lookup.c @@ -37,10 +37,10 @@ nftnl_expr_lookup_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_LOOKUP_SREG: - memcpy(&lookup->sreg, data, sizeof(lookup->sreg)); + memcpy(&lookup->sreg, data, data_len); break; case NFTNL_EXPR_LOOKUP_DREG: - memcpy(&lookup->dreg, data, sizeof(lookup->dreg)); + memcpy(&lookup->dreg, data, data_len); break; case NFTNL_EXPR_LOOKUP_SET: lookup->set_name = strdup((const char *)data); @@ -48,13 +48,11 @@ nftnl_expr_lookup_set(struct nftnl_expr *e, uint16_t type, return -1; break; case NFTNL_EXPR_LOOKUP_SET_ID: - memcpy(&lookup->set_id, data, sizeof(lookup->set_id)); + memcpy(&lookup->set_id, data, data_len); break; case NFTNL_EXPR_LOOKUP_FLAGS: - memcpy(&lookup->flags, data, sizeof(lookup->flags)); + memcpy(&lookup->flags, data, data_len); break; - default: - return -1; } return 0; } @@ -197,14 +195,23 @@ static void nftnl_expr_lookup_free(const struct nftnl_expr *e) xfree(lookup->set_name); } +static struct attr_policy lookup_attr_policy[__NFTNL_EXPR_LOOKUP_MAX] = { + [NFTNL_EXPR_LOOKUP_SREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_LOOKUP_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_LOOKUP_SET] = { .maxlen = NFT_SET_MAXNAMELEN }, + [NFTNL_EXPR_LOOKUP_SET_ID] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_LOOKUP_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_lookup = { .name = "lookup", .alloc_len = sizeof(struct nftnl_expr_lookup), - .max_attr = NFTA_LOOKUP_MAX, + .nftnl_max_attr = __NFTNL_EXPR_LOOKUP_MAX - 1, + .attr_policy = lookup_attr_policy, .free = nftnl_expr_lookup_free, .set = nftnl_expr_lookup_set, .get = nftnl_expr_lookup_get, .parse = nftnl_expr_lookup_parse, .build = nftnl_expr_lookup_build, - .snprintf = nftnl_expr_lookup_snprintf, + .output = nftnl_expr_lookup_snprintf, }; diff --git a/src/expr/masq.c b/src/expr/masq.c index 684708c..e0565db 100644 --- a/src/expr/masq.c +++ b/src/expr/masq.c @@ -34,16 +34,14 @@ nftnl_expr_masq_set(struct nftnl_expr *e, uint16_t type, switch (type) { case NFTNL_EXPR_MASQ_FLAGS: - memcpy(&masq->flags, data, sizeof(masq->flags)); + memcpy(&masq->flags, data, data_len); break; case NFTNL_EXPR_MASQ_REG_PROTO_MIN: - memcpy(&masq->sreg_proto_min, data, sizeof(masq->sreg_proto_min)); + memcpy(&masq->sreg_proto_min, data, data_len); break; case NFTNL_EXPR_MASQ_REG_PROTO_MAX: - memcpy(&masq->sreg_proto_max, data, sizeof(masq->sreg_proto_max)); + memcpy(&masq->sreg_proto_max, data, data_len); break; - default: - return -1; } return 0; } @@ -155,13 +153,20 @@ static int nftnl_expr_masq_snprintf(char *buf, size_t remain, return offset; } +static struct attr_policy masq_attr_policy[__NFTNL_EXPR_MASQ_MAX] = { + [NFTNL_EXPR_MASQ_FLAGS] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_MASQ_REG_PROTO_MIN] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_MASQ_REG_PROTO_MAX] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_masq = { .name = "masq", .alloc_len = sizeof(struct nftnl_expr_masq), - .max_attr = NFTA_MASQ_MAX, + .nftnl_max_attr = __NFTNL_EXPR_MASQ_MAX - 1, + .attr_policy = masq_attr_policy, .set = nftnl_expr_masq_set, .get = nftnl_expr_masq_get, .parse = nftnl_expr_masq_parse, .build = nftnl_expr_masq_build, - .snprintf = nftnl_expr_masq_snprintf, + .output = nftnl_expr_masq_snprintf, }; diff --git a/src/expr/match.c b/src/expr/match.c index 533fdf5..8c1bc74 100644 --- a/src/expr/match.c +++ b/src/expr/match.c @@ -46,7 +46,7 @@ nftnl_expr_match_set(struct nftnl_expr *e, uint16_t type, (const char *)data); break; case NFTNL_EXPR_MT_REV: - memcpy(&mt->rev, data, sizeof(mt->rev)); + memcpy(&mt->rev, data, data_len); break; case NFTNL_EXPR_MT_INFO: if (e->flags & (1 << NFTNL_EXPR_MT_INFO)) @@ -55,8 +55,6 @@ nftnl_expr_match_set(struct nftnl_expr *e, uint16_t type, mt->data = data; mt->data_len = data_len; break; - default: - return -1; } return 0; } @@ -180,14 +178,21 @@ static void nftnl_expr_match_free(const struct nftnl_expr *e) xfree(match->data); } +static struct attr_policy match_attr_policy[__NFTNL_EXPR_MT_MAX] = { + [NFTNL_EXPR_MT_NAME] = { .maxlen = XT_EXTENSION_MAXNAMELEN }, + [NFTNL_EXPR_MT_REV] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_MT_INFO] = { .maxlen = 0 }, +}; + struct expr_ops expr_ops_match = { .name = "match", .alloc_len = sizeof(struct nftnl_expr_match), - .max_attr = NFTA_MATCH_MAX, + .nftnl_max_attr = __NFTNL_EXPR_MT_MAX - 1, + .attr_policy = match_attr_policy, .free = nftnl_expr_match_free, .set = nftnl_expr_match_set, .get = nftnl_expr_match_get, .parse = nftnl_expr_match_parse, .build = nftnl_expr_match_build, - .snprintf = nftnl_expr_match_snprintf, + .output = nftnl_expr_match_snprintf, }; diff --git a/src/expr/meta.c b/src/expr/meta.c index 34fbb9b..136a450 100644 --- a/src/expr/meta.c +++ b/src/expr/meta.c @@ -22,7 +22,7 @@ #include <libnftnl/rule.h> #ifndef NFT_META_MAX -#define NFT_META_MAX (NFT_META_SDIFNAME + 1) +#define NFT_META_MAX (NFT_META_BRI_BROUTE + 1) #endif struct nftnl_expr_meta { @@ -39,16 +39,14 @@ nftnl_expr_meta_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_META_KEY: - memcpy(&meta->key, data, sizeof(meta->key)); + memcpy(&meta->key, data, data_len); break; case NFTNL_EXPR_META_DREG: - memcpy(&meta->dreg, data, sizeof(meta->dreg)); + memcpy(&meta->dreg, data, data_len); break; case NFTNL_EXPR_META_SREG: - memcpy(&meta->sreg, data, sizeof(meta->sreg)); + memcpy(&meta->sreg, data, data_len); break; - default: - return -1; } return 0; } @@ -168,6 +166,7 @@ static const char *meta_key2str_array[NFT_META_MAX] = { [NFT_META_TIME_HOUR] = "hour", [NFT_META_SDIF] = "sdif", [NFT_META_SDIFNAME] = "sdifname", + [NFT_META_BRI_BROUTE] = "broute", }; static const char *meta_key2str(uint8_t key) @@ -208,13 +207,20 @@ nftnl_expr_meta_snprintf(char *buf, size_t len, return 0; } +static struct attr_policy meta_attr_policy[__NFTNL_EXPR_META_MAX] = { + [NFTNL_EXPR_META_KEY] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_META_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_META_SREG] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_meta = { .name = "meta", .alloc_len = sizeof(struct nftnl_expr_meta), - .max_attr = NFTA_META_MAX, + .nftnl_max_attr = __NFTNL_EXPR_META_MAX - 1, + .attr_policy = meta_attr_policy, .set = nftnl_expr_meta_set, .get = nftnl_expr_meta_get, .parse = nftnl_expr_meta_parse, .build = nftnl_expr_meta_build, - .snprintf = nftnl_expr_meta_snprintf, + .output = nftnl_expr_meta_snprintf, }; diff --git a/src/expr/nat.c b/src/expr/nat.c index 0a9cdd7..1235ba4 100644 --- a/src/expr/nat.c +++ b/src/expr/nat.c @@ -42,28 +42,26 @@ nftnl_expr_nat_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_NAT_TYPE: - memcpy(&nat->type, data, sizeof(nat->type)); + memcpy(&nat->type, data, data_len); break; case NFTNL_EXPR_NAT_FAMILY: - memcpy(&nat->family, data, sizeof(nat->family)); + memcpy(&nat->family, data, data_len); break; case NFTNL_EXPR_NAT_REG_ADDR_MIN: - memcpy(&nat->sreg_addr_min, data, sizeof(nat->sreg_addr_min)); + memcpy(&nat->sreg_addr_min, data, data_len); break; case NFTNL_EXPR_NAT_REG_ADDR_MAX: - memcpy(&nat->sreg_addr_max, data, sizeof(nat->sreg_addr_max)); + memcpy(&nat->sreg_addr_max, data, data_len); break; case NFTNL_EXPR_NAT_REG_PROTO_MIN: - memcpy(&nat->sreg_proto_min, data, sizeof(nat->sreg_proto_min)); + memcpy(&nat->sreg_proto_min, data, data_len); break; case NFTNL_EXPR_NAT_REG_PROTO_MAX: - memcpy(&nat->sreg_proto_max, data, sizeof(nat->sreg_proto_max)); + memcpy(&nat->sreg_proto_max, data, data_len); break; case NFTNL_EXPR_NAT_FLAGS: - memcpy(&nat->flags, data, sizeof(nat->flags)); + memcpy(&nat->flags, data, data_len); break; - default: - return -1; } return 0; @@ -266,13 +264,24 @@ nftnl_expr_nat_snprintf(char *buf, size_t remain, return offset; } +static struct attr_policy nat_attr_policy[__NFTNL_EXPR_NAT_MAX] = { + [NFTNL_EXPR_NAT_TYPE] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_NAT_FAMILY] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_NAT_REG_ADDR_MIN] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_NAT_REG_ADDR_MAX] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_NAT_REG_PROTO_MIN] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_NAT_REG_PROTO_MAX] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_NAT_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_nat = { .name = "nat", .alloc_len = sizeof(struct nftnl_expr_nat), - .max_attr = NFTA_NAT_MAX, + .nftnl_max_attr = __NFTNL_EXPR_NAT_MAX - 1, + .attr_policy = nat_attr_policy, .set = nftnl_expr_nat_set, .get = nftnl_expr_nat_get, .parse = nftnl_expr_nat_parse, .build = nftnl_expr_nat_build, - .snprintf = nftnl_expr_nat_snprintf, + .output = nftnl_expr_nat_snprintf, }; diff --git a/src/expr/numgen.c b/src/expr/numgen.c index 159dfec..c015b88 100644 --- a/src/expr/numgen.c +++ b/src/expr/numgen.c @@ -35,16 +35,16 @@ nftnl_expr_ng_set(struct nftnl_expr *e, uint16_t type, switch (type) { case NFTNL_EXPR_NG_DREG: - memcpy(&ng->dreg, data, sizeof(ng->dreg)); + memcpy(&ng->dreg, data, data_len); break; case NFTNL_EXPR_NG_MODULUS: - memcpy(&ng->modulus, data, sizeof(ng->modulus)); + memcpy(&ng->modulus, data, data_len); break; case NFTNL_EXPR_NG_TYPE: - memcpy(&ng->type, data, sizeof(ng->type)); + memcpy(&ng->type, data, data_len); break; case NFTNL_EXPR_NG_OFFSET: - memcpy(&ng->offset, data, sizeof(ng->offset)); + memcpy(&ng->offset, data, data_len); break; default: return -1; @@ -172,13 +172,21 @@ nftnl_expr_ng_snprintf(char *buf, size_t remain, return offset; } +static struct attr_policy numgen_attr_policy[__NFTNL_EXPR_NG_MAX] = { + [NFTNL_EXPR_NG_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_NG_MODULUS] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_NG_TYPE] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_NG_OFFSET] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_ng = { .name = "numgen", .alloc_len = sizeof(struct nftnl_expr_ng), - .max_attr = NFTA_NG_MAX, + .nftnl_max_attr = __NFTNL_EXPR_NG_MAX - 1, + .attr_policy = numgen_attr_policy, .set = nftnl_expr_ng_set, .get = nftnl_expr_ng_get, .parse = nftnl_expr_ng_parse, .build = nftnl_expr_ng_build, - .snprintf = nftnl_expr_ng_snprintf, + .output = nftnl_expr_ng_snprintf, }; diff --git a/src/expr/objref.c b/src/expr/objref.c index a4b6470..0053805 100644 --- a/src/expr/objref.c +++ b/src/expr/objref.c @@ -39,7 +39,7 @@ static int nftnl_expr_objref_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_OBJREF_IMM_TYPE: - memcpy(&objref->imm.type, data, sizeof(objref->imm.type)); + memcpy(&objref->imm.type, data, data_len); break; case NFTNL_EXPR_OBJREF_IMM_NAME: objref->imm.name = strdup(data); @@ -47,7 +47,7 @@ static int nftnl_expr_objref_set(struct nftnl_expr *e, uint16_t type, return -1; break; case NFTNL_EXPR_OBJREF_SET_SREG: - memcpy(&objref->set.sreg, data, sizeof(objref->set.sreg)); + memcpy(&objref->set.sreg, data, data_len); break; case NFTNL_EXPR_OBJREF_SET_NAME: objref->set.name = strdup(data); @@ -55,10 +55,8 @@ static int nftnl_expr_objref_set(struct nftnl_expr *e, uint16_t type, return -1; break; case NFTNL_EXPR_OBJREF_SET_ID: - memcpy(&objref->set.id, data, sizeof(objref->set.id)); + memcpy(&objref->set.id, data, data_len); break; - default: - return -1; } return 0; } @@ -196,14 +194,23 @@ static void nftnl_expr_objref_free(const struct nftnl_expr *e) xfree(objref->set.name); } +static struct attr_policy objref_attr_policy[__NFTNL_EXPR_OBJREF_MAX] = { + [NFTNL_EXPR_OBJREF_IMM_TYPE] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_OBJREF_IMM_NAME] = { .maxlen = NFT_NAME_MAXLEN }, + [NFTNL_EXPR_OBJREF_SET_SREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_OBJREF_SET_NAME] = { .maxlen = NFT_NAME_MAXLEN }, + [NFTNL_EXPR_OBJREF_SET_ID] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_objref = { .name = "objref", .alloc_len = sizeof(struct nftnl_expr_objref), - .max_attr = NFTA_OBJREF_MAX, + .nftnl_max_attr = __NFTNL_EXPR_OBJREF_MAX - 1, + .attr_policy = objref_attr_policy, .free = nftnl_expr_objref_free, .set = nftnl_expr_objref_set, .get = nftnl_expr_objref_get, .parse = nftnl_expr_objref_parse, .build = nftnl_expr_objref_build, - .snprintf = nftnl_expr_objref_snprintf, + .output = nftnl_expr_objref_snprintf, }; diff --git a/src/expr/osf.c b/src/expr/osf.c index 215a681..060394b 100644 --- a/src/expr/osf.c +++ b/src/expr/osf.c @@ -25,13 +25,13 @@ static int nftnl_expr_osf_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_OSF_DREG: - memcpy(&osf->dreg, data, sizeof(osf->dreg)); + memcpy(&osf->dreg, data, data_len); break; case NFTNL_EXPR_OSF_TTL: - memcpy(&osf->ttl, data, sizeof(osf->ttl)); + memcpy(&osf->ttl, data, data_len); break; case NFTNL_EXPR_OSF_FLAGS: - memcpy(&osf->flags, data, sizeof(osf->flags)); + memcpy(&osf->flags, data, data_len); break; } return 0; @@ -139,13 +139,20 @@ nftnl_expr_osf_snprintf(char *buf, size_t len, return offset; } +static struct attr_policy osf_attr_policy[__NFTNL_EXPR_OSF_MAX] = { + [NFTNL_EXPR_OSF_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_OSF_TTL] = { .maxlen = sizeof(uint8_t) }, + [NFTNL_EXPR_OSF_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_osf = { .name = "osf", .alloc_len = sizeof(struct nftnl_expr_osf), - .max_attr = NFTA_OSF_MAX, + .nftnl_max_attr = __NFTNL_EXPR_OSF_MAX - 1, + .attr_policy = osf_attr_policy, .set = nftnl_expr_osf_set, .get = nftnl_expr_osf_get, .parse = nftnl_expr_osf_parse, .build = nftnl_expr_osf_build, - .snprintf = nftnl_expr_osf_snprintf, + .output = nftnl_expr_osf_snprintf, }; diff --git a/src/expr/payload.c b/src/expr/payload.c index 9ccb78e..35cd10c 100644 --- a/src/expr/payload.c +++ b/src/expr/payload.c @@ -43,31 +43,29 @@ nftnl_expr_payload_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_PAYLOAD_SREG: - memcpy(&payload->sreg, data, sizeof(payload->sreg)); + memcpy(&payload->sreg, data, data_len); break; case NFTNL_EXPR_PAYLOAD_DREG: - memcpy(&payload->dreg, data, sizeof(payload->dreg)); + memcpy(&payload->dreg, data, data_len); break; case NFTNL_EXPR_PAYLOAD_BASE: - memcpy(&payload->base, data, sizeof(payload->base)); + memcpy(&payload->base, data, data_len); break; case NFTNL_EXPR_PAYLOAD_OFFSET: - memcpy(&payload->offset, data, sizeof(payload->offset)); + memcpy(&payload->offset, data, data_len); break; case NFTNL_EXPR_PAYLOAD_LEN: - memcpy(&payload->len, data, sizeof(payload->len)); + memcpy(&payload->len, data, data_len); break; case NFTNL_EXPR_PAYLOAD_CSUM_TYPE: - memcpy(&payload->csum_type, data, sizeof(payload->csum_type)); + memcpy(&payload->csum_type, data, data_len); break; case NFTNL_EXPR_PAYLOAD_CSUM_OFFSET: - memcpy(&payload->csum_offset, data, sizeof(payload->csum_offset)); + memcpy(&payload->csum_offset, data, data_len); break; case NFTNL_EXPR_PAYLOAD_FLAGS: - memcpy(&payload->csum_flags, data, sizeof(payload->csum_flags)); + memcpy(&payload->csum_flags, data, data_len); break; - default: - return -1; } return 0; } @@ -203,34 +201,22 @@ nftnl_expr_payload_parse(struct nftnl_expr *e, struct nlattr *attr) return 0; } -static const char *base2str_array[NFT_PAYLOAD_TRANSPORT_HEADER+1] = { +static const char *base2str_array[NFT_PAYLOAD_TUN_HEADER + 1] = { [NFT_PAYLOAD_LL_HEADER] = "link", [NFT_PAYLOAD_NETWORK_HEADER] = "network", [NFT_PAYLOAD_TRANSPORT_HEADER] = "transport", + [NFT_PAYLOAD_INNER_HEADER] = "inner", + [NFT_PAYLOAD_TUN_HEADER] = "tunnel", }; static const char *base2str(enum nft_payload_bases base) { - if (base > NFT_PAYLOAD_TRANSPORT_HEADER) + if (base > NFT_PAYLOAD_INNER_HEADER) return "unknown"; return base2str_array[base]; } -static inline int nftnl_str2base(const char *base) -{ - if (strcmp(base, "link") == 0) - return NFT_PAYLOAD_LL_HEADER; - else if (strcmp(base, "network") == 0) - return NFT_PAYLOAD_NETWORK_HEADER; - else if (strcmp(base, "transport") == 0) - return NFT_PAYLOAD_TRANSPORT_HEADER; - else { - errno = EINVAL; - return -1; - } -} - static int nftnl_expr_payload_snprintf(char *buf, size_t len, uint32_t flags, const struct nftnl_expr *e) @@ -250,13 +236,25 @@ nftnl_expr_payload_snprintf(char *buf, size_t len, payload->offset, payload->dreg); } +static struct attr_policy payload_attr_policy[__NFTNL_EXPR_PAYLOAD_MAX] = { + [NFTNL_EXPR_PAYLOAD_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_PAYLOAD_BASE] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_PAYLOAD_OFFSET] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_PAYLOAD_LEN] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_PAYLOAD_SREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_PAYLOAD_CSUM_TYPE] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_PAYLOAD_CSUM_OFFSET] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_PAYLOAD_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_payload = { .name = "payload", .alloc_len = sizeof(struct nftnl_expr_payload), - .max_attr = NFTA_PAYLOAD_MAX, + .nftnl_max_attr = __NFTNL_EXPR_PAYLOAD_MAX - 1, + .attr_policy = payload_attr_policy, .set = nftnl_expr_payload_set, .get = nftnl_expr_payload_get, .parse = nftnl_expr_payload_parse, .build = nftnl_expr_payload_build, - .snprintf = nftnl_expr_payload_snprintf, + .output = nftnl_expr_payload_snprintf, }; diff --git a/src/expr/queue.c b/src/expr/queue.c index 8f70977..09220c4 100644 --- a/src/expr/queue.c +++ b/src/expr/queue.c @@ -34,19 +34,17 @@ static int nftnl_expr_queue_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_QUEUE_NUM: - memcpy(&queue->queuenum, data, sizeof(queue->queuenum)); + memcpy(&queue->queuenum, data, data_len); break; case NFTNL_EXPR_QUEUE_TOTAL: - memcpy(&queue->queues_total, data, sizeof(queue->queues_total)); + memcpy(&queue->queues_total, data, data_len); break; case NFTNL_EXPR_QUEUE_FLAGS: - memcpy(&queue->flags, data, sizeof(queue->flags)); + memcpy(&queue->flags, data, data_len); break; case NFTNL_EXPR_QUEUE_SREG_QNUM: - memcpy(&queue->sreg_qnum, data, sizeof(queue->sreg_qnum)); + memcpy(&queue->sreg_qnum, data, data_len); break; - default: - return -1; } return 0; } @@ -185,13 +183,21 @@ nftnl_expr_queue_snprintf(char *buf, size_t remain, return offset; } +static struct attr_policy queue_attr_policy[__NFTNL_EXPR_QUEUE_MAX] = { + [NFTNL_EXPR_QUEUE_NUM] = { .maxlen = sizeof(uint16_t) }, + [NFTNL_EXPR_QUEUE_TOTAL] = { .maxlen = sizeof(uint16_t) }, + [NFTNL_EXPR_QUEUE_FLAGS] = { .maxlen = sizeof(uint16_t) }, + [NFTNL_EXPR_QUEUE_SREG_QNUM] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_queue = { .name = "queue", .alloc_len = sizeof(struct nftnl_expr_queue), - .max_attr = NFTA_QUEUE_MAX, + .nftnl_max_attr = __NFTNL_EXPR_QUEUE_MAX - 1, + .attr_policy = queue_attr_policy, .set = nftnl_expr_queue_set, .get = nftnl_expr_queue_get, .parse = nftnl_expr_queue_parse, .build = nftnl_expr_queue_build, - .snprintf = nftnl_expr_queue_snprintf, + .output = nftnl_expr_queue_snprintf, }; diff --git a/src/expr/quota.c b/src/expr/quota.c index 8c841d8..ddf232f 100644 --- a/src/expr/quota.c +++ b/src/expr/quota.c @@ -33,16 +33,14 @@ static int nftnl_expr_quota_set(struct nftnl_expr *e, uint16_t type, switch (type) { case NFTNL_EXPR_QUOTA_BYTES: - memcpy("a->bytes, data, sizeof(quota->bytes)); + memcpy("a->bytes, data, data_len); break; case NFTNL_EXPR_QUOTA_CONSUMED: - memcpy("a->consumed, data, sizeof(quota->consumed)); + memcpy("a->consumed, data, data_len); break; case NFTNL_EXPR_QUOTA_FLAGS: - memcpy("a->flags, data, sizeof(quota->flags)); + memcpy("a->flags, data, data_len); break; - default: - return -1; } return 0; } @@ -139,13 +137,20 @@ static int nftnl_expr_quota_snprintf(char *buf, size_t len, quota->bytes, quota->consumed, quota->flags); } +static struct attr_policy quota_attr_policy[__NFTNL_EXPR_QUOTA_MAX] = { + [NFTNL_EXPR_QUOTA_BYTES] = { .maxlen = sizeof(uint64_t) }, + [NFTNL_EXPR_QUOTA_FLAGS] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_QUOTA_CONSUMED] = { .maxlen = sizeof(uint64_t) }, +}; + struct expr_ops expr_ops_quota = { .name = "quota", .alloc_len = sizeof(struct nftnl_expr_quota), - .max_attr = NFTA_QUOTA_MAX, + .nftnl_max_attr = __NFTNL_EXPR_QUOTA_MAX - 1, + .attr_policy = quota_attr_policy, .set = nftnl_expr_quota_set, .get = nftnl_expr_quota_get, .parse = nftnl_expr_quota_parse, .build = nftnl_expr_quota_build, - .snprintf = nftnl_expr_quota_snprintf, + .output = nftnl_expr_quota_snprintf, }; diff --git a/src/expr/range.c b/src/expr/range.c index f76843a..96bb140 100644 --- a/src/expr/range.c +++ b/src/expr/range.c @@ -34,21 +34,15 @@ static int nftnl_expr_range_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_RANGE_SREG: - memcpy(&range->sreg, data, sizeof(range->sreg)); + memcpy(&range->sreg, data, data_len); break; case NFTNL_EXPR_RANGE_OP: - memcpy(&range->op, data, sizeof(range->op)); + memcpy(&range->op, data, data_len); break; case NFTNL_EXPR_RANGE_FROM_DATA: - memcpy(&range->data_from.val, data, data_len); - range->data_from.len = data_len; - break; + return nftnl_data_cpy(&range->data_from, data, data_len); case NFTNL_EXPR_RANGE_TO_DATA: - memcpy(&range->data_to.val, data, data_len); - range->data_to.len = data_len; - break; - default: - return -1; + return nftnl_data_cpy(&range->data_to, data, data_len); } return 0; } @@ -205,13 +199,21 @@ static int nftnl_expr_range_snprintf(char *buf, size_t remain, return offset; } +static struct attr_policy range_attr_policy[__NFTNL_EXPR_RANGE_MAX] = { + [NFTNL_EXPR_RANGE_SREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_RANGE_OP] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_RANGE_FROM_DATA] = { .maxlen = NFT_DATA_VALUE_MAXLEN }, + [NFTNL_EXPR_RANGE_TO_DATA] = { .maxlen = NFT_DATA_VALUE_MAXLEN }, +}; + struct expr_ops expr_ops_range = { .name = "range", .alloc_len = sizeof(struct nftnl_expr_range), - .max_attr = NFTA_RANGE_MAX, + .nftnl_max_attr = __NFTNL_EXPR_RANGE_MAX - 1, + .attr_policy = range_attr_policy, .set = nftnl_expr_range_set, .get = nftnl_expr_range_get, .parse = nftnl_expr_range_parse, .build = nftnl_expr_range_build, - .snprintf = nftnl_expr_range_snprintf, + .output = nftnl_expr_range_snprintf, }; diff --git a/src/expr/redir.c b/src/expr/redir.c index 4f56cb4..9971306 100644 --- a/src/expr/redir.c +++ b/src/expr/redir.c @@ -34,16 +34,14 @@ nftnl_expr_redir_set(struct nftnl_expr *e, uint16_t type, switch (type) { case NFTNL_EXPR_REDIR_REG_PROTO_MIN: - memcpy(&redir->sreg_proto_min, data, sizeof(redir->sreg_proto_min)); + memcpy(&redir->sreg_proto_min, data, data_len); break; case NFTNL_EXPR_REDIR_REG_PROTO_MAX: - memcpy(&redir->sreg_proto_max, data, sizeof(redir->sreg_proto_max)); + memcpy(&redir->sreg_proto_max, data, data_len); break; case NFTNL_EXPR_REDIR_FLAGS: - memcpy(&redir->flags, data, sizeof(redir->flags)); + memcpy(&redir->flags, data, data_len); break; - default: - return -1; } return 0; } @@ -159,13 +157,20 @@ nftnl_expr_redir_snprintf(char *buf, size_t remain, return offset; } +static struct attr_policy redir_attr_policy[__NFTNL_EXPR_REDIR_MAX] = { + [NFTNL_EXPR_REDIR_REG_PROTO_MIN] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_REDIR_REG_PROTO_MAX] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_REDIR_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_redir = { .name = "redir", .alloc_len = sizeof(struct nftnl_expr_redir), - .max_attr = NFTA_REDIR_MAX, + .nftnl_max_attr = __NFTNL_EXPR_REDIR_MAX - 1, + .attr_policy = redir_attr_policy, .set = nftnl_expr_redir_set, .get = nftnl_expr_redir_get, .parse = nftnl_expr_redir_parse, .build = nftnl_expr_redir_build, - .snprintf = nftnl_expr_redir_snprintf, + .output = nftnl_expr_redir_snprintf, }; diff --git a/src/expr/reject.c b/src/expr/reject.c index 716d25c..9090db3 100644 --- a/src/expr/reject.c +++ b/src/expr/reject.c @@ -33,13 +33,11 @@ static int nftnl_expr_reject_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_REJECT_TYPE: - memcpy(&reject->type, data, sizeof(reject->type)); + memcpy(&reject->type, data, data_len); break; case NFTNL_EXPR_REJECT_CODE: - memcpy(&reject->icmp_code, data, sizeof(reject->icmp_code)); + memcpy(&reject->icmp_code, data, data_len); break; - default: - return -1; } return 0; } @@ -126,13 +124,19 @@ nftnl_expr_reject_snprintf(char *buf, size_t len, reject->type, reject->icmp_code); } +static struct attr_policy reject_attr_policy[__NFTNL_EXPR_REJECT_MAX] = { + [NFTNL_EXPR_REJECT_TYPE] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_REJECT_CODE] = { .maxlen = sizeof(uint8_t) }, +}; + struct expr_ops expr_ops_reject = { .name = "reject", .alloc_len = sizeof(struct nftnl_expr_reject), - .max_attr = NFTA_REJECT_MAX, + .nftnl_max_attr = __NFTNL_EXPR_REJECT_MAX - 1, + .attr_policy = reject_attr_policy, .set = nftnl_expr_reject_set, .get = nftnl_expr_reject_get, .parse = nftnl_expr_reject_parse, .build = nftnl_expr_reject_build, - .snprintf = nftnl_expr_reject_snprintf, + .output = nftnl_expr_reject_snprintf, }; diff --git a/src/expr/rt.c b/src/expr/rt.c index 1ad9b2a..ff4fd03 100644 --- a/src/expr/rt.c +++ b/src/expr/rt.c @@ -32,13 +32,11 @@ nftnl_expr_rt_set(struct nftnl_expr *e, uint16_t type, switch (type) { case NFTNL_EXPR_RT_KEY: - memcpy(&rt->key, data, sizeof(rt->key)); + memcpy(&rt->key, data, data_len); break; case NFTNL_EXPR_RT_DREG: - memcpy(&rt->dreg, data, sizeof(rt->dreg)); + memcpy(&rt->dreg, data, data_len); break; - default: - return -1; } return 0; } @@ -154,13 +152,19 @@ nftnl_expr_rt_snprintf(char *buf, size_t len, return 0; } +static struct attr_policy rt_attr_policy[__NFTNL_EXPR_RT_MAX] = { + [NFTNL_EXPR_RT_KEY] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_RT_DREG] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_rt = { .name = "rt", .alloc_len = sizeof(struct nftnl_expr_rt), - .max_attr = NFTA_RT_MAX, + .nftnl_max_attr = __NFTNL_EXPR_RT_MAX - 1, + .attr_policy = rt_attr_policy, .set = nftnl_expr_rt_set, .get = nftnl_expr_rt_get, .parse = nftnl_expr_rt_parse, .build = nftnl_expr_rt_build, - .snprintf = nftnl_expr_rt_snprintf, + .output = nftnl_expr_rt_snprintf, }; diff --git a/src/expr/socket.c b/src/expr/socket.c index 02d86f8..7a25cdf 100644 --- a/src/expr/socket.c +++ b/src/expr/socket.c @@ -33,16 +33,14 @@ nftnl_expr_socket_set(struct nftnl_expr *e, uint16_t type, switch (type) { case NFTNL_EXPR_SOCKET_KEY: - memcpy(&socket->key, data, sizeof(socket->key)); + memcpy(&socket->key, data, data_len); break; case NFTNL_EXPR_SOCKET_DREG: - memcpy(&socket->dreg, data, sizeof(socket->dreg)); + memcpy(&socket->dreg, data, data_len); break; case NFTNL_EXPR_SOCKET_LEVEL: - memcpy(&socket->level, data, sizeof(socket->level)); + memcpy(&socket->level, data, data_len); break; - default: - return -1; } return 0; } @@ -157,13 +155,20 @@ nftnl_expr_socket_snprintf(char *buf, size_t len, return 0; } +static struct attr_policy socket_attr_policy[__NFTNL_EXPR_SOCKET_MAX] = { + [NFTNL_EXPR_SOCKET_KEY] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_SOCKET_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_SOCKET_LEVEL] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_socket = { .name = "socket", .alloc_len = sizeof(struct nftnl_expr_socket), - .max_attr = NFTA_SOCKET_MAX, + .nftnl_max_attr = __NFTNL_EXPR_SOCKET_MAX - 1, + .attr_policy = socket_attr_policy, .set = nftnl_expr_socket_set, .get = nftnl_expr_socket_get, .parse = nftnl_expr_socket_parse, .build = nftnl_expr_socket_build, - .snprintf = nftnl_expr_socket_snprintf, + .output = nftnl_expr_socket_snprintf, }; diff --git a/src/expr/synproxy.c b/src/expr/synproxy.c index 630f3f4..97c321b 100644 --- a/src/expr/synproxy.c +++ b/src/expr/synproxy.c @@ -23,13 +23,13 @@ static int nftnl_expr_synproxy_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_SYNPROXY_MSS: - memcpy(&synproxy->mss, data, sizeof(synproxy->mss)); + memcpy(&synproxy->mss, data, data_len); break; case NFTNL_EXPR_SYNPROXY_WSCALE: - memcpy(&synproxy->wscale, data, sizeof(synproxy->wscale)); + memcpy(&synproxy->wscale, data, data_len); break; case NFTNL_EXPR_SYNPROXY_FLAGS: - memcpy(&synproxy->flags, data, sizeof(synproxy->flags)); + memcpy(&synproxy->flags, data, data_len); break; } return 0; @@ -144,13 +144,20 @@ nftnl_expr_synproxy_snprintf(char *buf, size_t len, return offset; } +static struct attr_policy synproxy_attr_policy[__NFTNL_EXPR_SYNPROXY_MAX] = { + [NFTNL_EXPR_SYNPROXY_MSS] = { .maxlen = sizeof(uint16_t) }, + [NFTNL_EXPR_SYNPROXY_WSCALE] = { .maxlen = sizeof(uint8_t) }, + [NFTNL_EXPR_SYNPROXY_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_synproxy = { .name = "synproxy", .alloc_len = sizeof(struct nftnl_expr_synproxy), - .max_attr = NFTA_SYNPROXY_MAX, + .nftnl_max_attr = __NFTNL_EXPR_SYNPROXY_MAX - 1, + .attr_policy = synproxy_attr_policy, .set = nftnl_expr_synproxy_set, .get = nftnl_expr_synproxy_get, .parse = nftnl_expr_synproxy_parse, .build = nftnl_expr_synproxy_build, - .snprintf = nftnl_expr_synproxy_snprintf, + .output = nftnl_expr_synproxy_snprintf, }; diff --git a/src/expr/target.c b/src/expr/target.c index b7c595a..8259a20 100644 --- a/src/expr/target.c +++ b/src/expr/target.c @@ -46,7 +46,7 @@ nftnl_expr_target_set(struct nftnl_expr *e, uint16_t type, (const char *) data); break; case NFTNL_EXPR_TG_REV: - memcpy(&tg->rev, data, sizeof(tg->rev)); + memcpy(&tg->rev, data, data_len); break; case NFTNL_EXPR_TG_INFO: if (e->flags & (1 << NFTNL_EXPR_TG_INFO)) @@ -55,8 +55,6 @@ nftnl_expr_target_set(struct nftnl_expr *e, uint16_t type, tg->data = data; tg->data_len = data_len; break; - default: - return -1; } return 0; } @@ -180,14 +178,21 @@ static void nftnl_expr_target_free(const struct nftnl_expr *e) xfree(target->data); } +static struct attr_policy target_attr_policy[__NFTNL_EXPR_TG_MAX] = { + [NFTNL_EXPR_TG_NAME] = { .maxlen = XT_EXTENSION_MAXNAMELEN }, + [NFTNL_EXPR_TG_REV] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_TG_INFO] = { .maxlen = 0 }, +}; + struct expr_ops expr_ops_target = { .name = "target", .alloc_len = sizeof(struct nftnl_expr_target), - .max_attr = NFTA_TARGET_MAX, + .nftnl_max_attr = __NFTNL_EXPR_TG_MAX - 1, + .attr_policy = target_attr_policy, .free = nftnl_expr_target_free, .set = nftnl_expr_target_set, .get = nftnl_expr_target_get, .parse = nftnl_expr_target_parse, .build = nftnl_expr_target_build, - .snprintf = nftnl_expr_target_snprintf, + .output = nftnl_expr_target_snprintf, }; diff --git a/src/expr/tproxy.c b/src/expr/tproxy.c index d3ee8f8..9391ce8 100644 --- a/src/expr/tproxy.c +++ b/src/expr/tproxy.c @@ -34,16 +34,14 @@ nftnl_expr_tproxy_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_TPROXY_FAMILY: - memcpy(&tproxy->family, data, sizeof(tproxy->family)); + memcpy(&tproxy->family, data, data_len); break; case NFTNL_EXPR_TPROXY_REG_ADDR: - memcpy(&tproxy->sreg_addr, data, sizeof(tproxy->sreg_addr)); + memcpy(&tproxy->sreg_addr, data, data_len); break; case NFTNL_EXPR_TPROXY_REG_PORT: - memcpy(&tproxy->sreg_port, data, sizeof(tproxy->sreg_port)); + memcpy(&tproxy->sreg_port, data, data_len); break; - default: - return -1; } return 0; @@ -162,13 +160,20 @@ nftnl_expr_tproxy_snprintf(char *buf, size_t remain, return offset; } +static struct attr_policy tproxy_attr_policy[__NFTNL_EXPR_TPROXY_MAX] = { + [NFTNL_EXPR_TPROXY_FAMILY] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_TPROXY_REG_ADDR] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_TPROXY_REG_PORT] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_tproxy = { .name = "tproxy", .alloc_len = sizeof(struct nftnl_expr_tproxy), - .max_attr = NFTA_TPROXY_MAX, + .nftnl_max_attr = __NFTNL_EXPR_TPROXY_MAX - 1, + .attr_policy = tproxy_attr_policy, .set = nftnl_expr_tproxy_set, .get = nftnl_expr_tproxy_get, .parse = nftnl_expr_tproxy_parse, .build = nftnl_expr_tproxy_build, - .snprintf = nftnl_expr_tproxy_snprintf, + .output = nftnl_expr_tproxy_snprintf, }; diff --git a/src/expr/tunnel.c b/src/expr/tunnel.c index 1460fd2..861e56d 100644 --- a/src/expr/tunnel.c +++ b/src/expr/tunnel.c @@ -31,13 +31,11 @@ static int nftnl_expr_tunnel_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_TUNNEL_KEY: - memcpy(&tunnel->key, data, sizeof(tunnel->key)); + memcpy(&tunnel->key, data, data_len); break; case NFTNL_EXPR_TUNNEL_DREG: - memcpy(&tunnel->dreg, data, sizeof(tunnel->dreg)); + memcpy(&tunnel->dreg, data, data_len); break; - default: - return -1; } return 0; } @@ -137,13 +135,19 @@ nftnl_expr_tunnel_snprintf(char *buf, size_t len, return 0; } +static struct attr_policy tunnel_attr_policy[__NFTNL_EXPR_TUNNEL_MAX] = { + [NFTNL_EXPR_TUNNEL_KEY] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_TUNNEL_DREG] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_tunnel = { .name = "tunnel", .alloc_len = sizeof(struct nftnl_expr_tunnel), - .max_attr = NFTA_TUNNEL_MAX, + .nftnl_max_attr = __NFTNL_EXPR_TUNNEL_MAX - 1, + .attr_policy = tunnel_attr_policy, .set = nftnl_expr_tunnel_set, .get = nftnl_expr_tunnel_get, .parse = nftnl_expr_tunnel_parse, .build = nftnl_expr_tunnel_build, - .snprintf = nftnl_expr_tunnel_snprintf, + .output = nftnl_expr_tunnel_snprintf, }; diff --git a/src/expr/xfrm.c b/src/expr/xfrm.c index c81d14d..2585579 100644 --- a/src/expr/xfrm.c +++ b/src/expr/xfrm.c @@ -33,16 +33,16 @@ nftnl_expr_xfrm_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_XFRM_KEY: - memcpy(&x->key, data, sizeof(x->key)); + memcpy(&x->key, data, data_len); break; case NFTNL_EXPR_XFRM_DIR: - memcpy(&x->dir, data, sizeof(x->dir)); + memcpy(&x->dir, data, data_len); break; case NFTNL_EXPR_XFRM_SPNUM: - memcpy(&x->spnum, data, sizeof(x->spnum)); + memcpy(&x->spnum, data, data_len); break; case NFTNL_EXPR_XFRM_DREG: - memcpy(&x->dreg, data, sizeof(x->dreg)); + memcpy(&x->dreg, data, data_len); break; default: return -1; @@ -188,13 +188,22 @@ nftnl_expr_xfrm_snprintf(char *buf, size_t remain, return offset; } +static struct attr_policy xfrm_attr_policy[__NFTNL_EXPR_XFRM_MAX] = { + [NFTNL_EXPR_XFRM_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_XFRM_SREG] = { .maxlen = 0 }, + [NFTNL_EXPR_XFRM_KEY] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_XFRM_DIR] = { .maxlen = sizeof(uint8_t) }, + [NFTNL_EXPR_XFRM_SPNUM] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_xfrm = { .name = "xfrm", .alloc_len = sizeof(struct nftnl_expr_xfrm), - .max_attr = NFTA_XFRM_MAX, + .nftnl_max_attr = __NFTNL_EXPR_XFRM_MAX - 1, + .attr_policy = xfrm_attr_policy, .set = nftnl_expr_xfrm_set, .get = nftnl_expr_xfrm_get, .parse = nftnl_expr_xfrm_parse, .build = nftnl_expr_xfrm_build, - .snprintf = nftnl_expr_xfrm_snprintf, + .output = nftnl_expr_xfrm_snprintf, }; |