String is an unqualified type and we do not have a data element to derive the element size from at set creation time. Add a new string subtype -- iface_name -- and switch meta iifname/oifname to use it instead of string. One can then define a named set for interface names with nft add set filter ifnames '{type iface_name; }' Signed-off-by: Florian Westphal <fw@xxxxxxxxx> --- doc/nft.xml | 6 +++--- include/datatype.h | 2 ++ src/evaluate.c | 9 +++++---- src/meta.c | 31 +++++++++++++++++++++++++++---- src/netlink_delinearize.c | 6 +++--- src/netlink_linearize.c | 2 +- 6 files changed, 41 insertions(+), 15 deletions(-) diff --git a/doc/nft.xml b/doc/nft.xml index 7cc9988..b94e696 100644 --- a/doc/nft.xml +++ b/doc/nft.xml @@ -1044,7 +1044,7 @@ filter output ip6 daddr ::1 <row> <entry>iifname</entry> <entry>Input interface name</entry> - <entry>string</entry> + <entry>iface_name</entry> </row> <row> <entry>iiftype</entry> @@ -1059,7 +1059,7 @@ filter output ip6 daddr ::1 <row> <entry>oifname</entry> <entry>Output interface name</entry> - <entry>string</entry> + <entry>iface_name</entry> </row> <row> <entry>oiftype</entry> @@ -1141,7 +1141,7 @@ filter output ip6 daddr ::1 </entry> </row> <row> - <entry>ifname</entry> + <entry>iface_type</entry> <entry> Interface name (16 byte string). Does not have to exist. </entry> diff --git a/include/datatype.h b/include/datatype.h index 91ca2dd..91aa550 100644 --- a/include/datatype.h +++ b/include/datatype.h @@ -40,6 +40,7 @@ * @TYPE_ICMPV6_CODE: icmpv6 code (integer subtype) * @TYPE_ICMPX_CODE: icmpx code (integer subtype) * @TYPE_DEVGROUP: devgroup code (integer subtype) + * @TYPE_IFNAME: interface name (string subtype) */ enum datatypes { TYPE_INVALID, @@ -78,6 +79,7 @@ enum datatypes { TYPE_ICMPV6_CODE, TYPE_ICMPX_CODE, TYPE_DEVGROUP, + TYPE_IFNAME, __TYPE_MAX }; #define TYPE_MAX (__TYPE_MAX - 1) diff --git a/src/evaluate.c b/src/evaluate.c index ed78896..1390900 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -209,6 +209,7 @@ static int expr_evaluate_string(struct eval_ctx *ctx, struct expr **exprp) unsigned int len = div_round_up(expr->len, BITS_PER_BYTE), datalen; struct expr *value, *prefix; int data_len = ctx->ectx.len > 0 ? ctx->ectx.len : len + 1; + const struct datatype *dtype = expr->dtype; char data[data_len]; if (ctx->ectx.len > 0) { @@ -227,7 +228,7 @@ static int expr_evaluate_string(struct eval_ctx *ctx, struct expr **exprp) /* We need to reallocate the constant expression with the right * expression length to avoid problems on big endian. */ - value = constant_expr_alloc(&expr->location, &string_type, + value = constant_expr_alloc(&expr->location, dtype, BYTEORDER_HOST_ENDIAN, expr->len, data); expr_free(expr); @@ -242,20 +243,20 @@ static int expr_evaluate_string(struct eval_ctx *ctx, struct expr **exprp) memset(unescaped_str, 0, sizeof(unescaped_str)); xstrunescape(data, unescaped_str); - value = constant_expr_alloc(&expr->location, &string_type, + value = constant_expr_alloc(&expr->location, dtype, BYTEORDER_HOST_ENDIAN, expr->len, unescaped_str); expr_free(expr); *exprp = value; return 0; } - value = constant_expr_alloc(&expr->location, &string_type, + value = constant_expr_alloc(&expr->location, dtype, BYTEORDER_HOST_ENDIAN, datalen * BITS_PER_BYTE, data); prefix = prefix_expr_alloc(&expr->location, value, datalen * BITS_PER_BYTE); - prefix->dtype = &string_type; + prefix->dtype = dtype; prefix->flags |= EXPR_F_CONSTANT; prefix->byteorder = BYTEORDER_HOST_ENDIAN; diff --git a/src/meta.c b/src/meta.c index b8db0f8..914d3c2 100644 --- a/src/meta.c +++ b/src/meta.c @@ -173,6 +173,28 @@ const struct datatype ifindex_type = { .parse = ifindex_type_parse, }; +static struct error_record *ifname_type_parse(const struct expr *sym, + struct expr **res); +const struct datatype ifname_type = { + .type = TYPE_IFNAME, + .name = "iface_name", + .desc = "network interface name", + .byteorder = BYTEORDER_HOST_ENDIAN, + .size = IFNAMSIZ * BITS_PER_BYTE, + .basetype = &string_type, + .parse = ifname_type_parse, +}; + +static struct error_record *ifname_type_parse(const struct expr *sym, + struct expr **res) +{ + *res = constant_expr_alloc(&sym->location, &ifname_type, + BYTEORDER_HOST_ENDIAN, + (strlen(sym->identifier) + 1) * BITS_PER_BYTE, + sym->identifier); + return NULL; +} + static const struct symbol_table arphrd_tbl = { .symbols = { SYMBOL("ether", ARPHRD_ETHER), @@ -375,14 +397,14 @@ static const struct meta_template meta_templates[] = { 4 * 8, BYTEORDER_HOST_ENDIAN), [NFT_META_IIF] = META_TEMPLATE("iif", &ifindex_type, 4 * 8, BYTEORDER_HOST_ENDIAN), - [NFT_META_IIFNAME] = META_TEMPLATE("iifname", &string_type, + [NFT_META_IIFNAME] = META_TEMPLATE("iifname", &ifname_type, IFNAMSIZ * BITS_PER_BYTE, BYTEORDER_HOST_ENDIAN), [NFT_META_IIFTYPE] = META_TEMPLATE("iiftype", &arphrd_type, 2 * 8, BYTEORDER_HOST_ENDIAN), [NFT_META_OIF] = META_TEMPLATE("oif", &ifindex_type, 4 * 8, BYTEORDER_HOST_ENDIAN), - [NFT_META_OIFNAME] = META_TEMPLATE("oifname", &string_type, + [NFT_META_OIFNAME] = META_TEMPLATE("oifname", &ifname_type, IFNAMSIZ * BITS_PER_BYTE, BYTEORDER_HOST_ENDIAN), [NFT_META_OIFTYPE] = META_TEMPLATE("oiftype", &arphrd_type, @@ -395,10 +417,10 @@ static const struct meta_template meta_templates[] = { 1 , BYTEORDER_HOST_ENDIAN), [NFT_META_RTCLASSID] = META_TEMPLATE("rtclassid", &realm_type, 4 * 8, BYTEORDER_HOST_ENDIAN), - [NFT_META_BRI_IIFNAME] = META_TEMPLATE("ibriport", &string_type, + [NFT_META_BRI_IIFNAME] = META_TEMPLATE("ibriport", &ifname_type, IFNAMSIZ * BITS_PER_BYTE, BYTEORDER_HOST_ENDIAN), - [NFT_META_BRI_OIFNAME] = META_TEMPLATE("obriport", &string_type, + [NFT_META_BRI_OIFNAME] = META_TEMPLATE("obriport", &ifname_type, IFNAMSIZ * BITS_PER_BYTE, BYTEORDER_HOST_ENDIAN), [NFT_META_PKTTYPE] = META_TEMPLATE("pkttype", &pkttype_type, @@ -583,6 +605,7 @@ struct stmt *meta_stmt_alloc(const struct location *loc, enum nft_meta_keys key, static void __init meta_init(void) { datatype_register(&ifindex_type); + datatype_register(&ifname_type); datatype_register(&realm_type); datatype_register(&tchandle_type); datatype_register(&uid_type); diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index ae6abb0..a28174c 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -233,7 +233,7 @@ static void netlink_parse_cmp(struct netlink_parse_ctx *ctx, right = netlink_alloc_value(loc, &nld); if (left->len > right->len && - left->dtype != &string_type) { + expr_basetype(left) != &string_type) { return netlink_error(ctx, loc, "Relational expression size mismatch"); } else if (left->len > 0 && left->len < right->len) { @@ -1383,7 +1383,7 @@ static struct expr *expr_postprocess_string(struct expr *expr) { struct expr *mask; - assert(expr->dtype->type == TYPE_STRING); + assert(expr_basetype(expr)->type == TYPE_STRING); if (__expr_postprocess_string(&expr)) return expr; @@ -1490,7 +1490,7 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp) if (expr->byteorder == BYTEORDER_HOST_ENDIAN) mpz_switch_byteorder(expr->value, expr->len / BITS_PER_BYTE); - if (expr->dtype->type == TYPE_STRING) + if (expr_basetype(expr)->type == TYPE_STRING) *exprp = expr_postprocess_string(expr); if (expr->dtype->basetype != NULL && diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c index 86b49c6..73d7944 100644 --- a/src/netlink_linearize.c +++ b/src/netlink_linearize.c @@ -349,7 +349,7 @@ static void netlink_gen_cmp(struct netlink_linearize_ctx *ctx, switch (expr->right->ops->type) { case EXPR_PREFIX: - if (expr->left->dtype->type != TYPE_STRING) { + if (expr_basetype(expr->left)->type != TYPE_STRING) { len = div_round_up(expr->right->len, BITS_PER_BYTE); netlink_gen_expr(ctx, expr->left, sreg); right = netlink_gen_prefix(ctx, expr, sreg); -- 2.4.10 -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html