]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
meta: introduce datatype ifname_type
authorArturo Borrero Gonzalez <arturo@netfilter.org>
Sun, 25 Feb 2018 17:30:24 +0000 (18:30 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Sun, 25 Feb 2018 22:09:02 +0000 (23:09 +0100)
This new datatype is a string subtype.
It will allow us to build named maps/sets using meta keys like 'iifname',
'oifname', 'ibriport' or 'obriport'.

Example:

table inet t {
set s {
type ifname
elements = { "eth0",
     "eth1" }
}

chain c {
iifname @s accept
oifname @s accept
}
}

Signed-off-by: Arturo Borrero Gonzalez <arturo@netfilter.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
doc/nft.xml
include/datatype.h
include/meta.h
src/datatype.c
src/evaluate.c
src/meta.c
src/netlink_delinearize.c
src/netlink_linearize.c
tests/shell/testcases/maps/0007named_ifname_dtype_0 [new file with mode: 0755]
tests/shell/testcases/sets/0029named_ifname_dtype_0 [new file with mode: 0755]

index 9d21e9a1120388971a13c2f9d94ba46efee2ca1d..6748265c8ae881a957ec65f605026eeab89b6670 100644 (file)
@@ -2572,7 +2572,7 @@ filter output icmpv6 type { echo-request, echo-reply }
                                                        <row>
                                                                <entry>iifname</entry>
                                                                <entry>Input interface name</entry>
-                                                               <entry>string</entry>
+                                                               <entry>ifname</entry>
                                                        </row>
                                                        <row>
                                                                <entry>iiftype</entry>
@@ -2587,7 +2587,7 @@ filter output icmpv6 type { echo-request, echo-reply }
                                                        <row>
                                                                <entry>oifname</entry>
                                                                <entry>Output interface name</entry>
-                                                               <entry>string</entry>
+                                                               <entry>ifname</entry>
                                                        </row>
                                                        <row>
                                                                <entry>oiftype</entry>
@@ -2612,12 +2612,12 @@ filter output icmpv6 type { echo-request, echo-reply }
                                                        <row>
                                                                <entry>ibriport</entry>
                                                                <entry>Input bridge interface name</entry>
-                                                               <entry>string</entry>
+                                                               <entry>ifname</entry>
                                                        </row>
                                                        <row>
                                                                <entry>obriport</entry>
                                                                <entry>Output bridge interface name</entry>
-                                                               <entry>string</entry>
+                                                               <entry>ifname</entry>
                                                        </row>
                                                        <row>
                                                                <entry>pkttype</entry>
index cc4cb07807d433211d60bbb000776d1b057acf5e..3f612e52aec29af300f065edb3bf9551d48784bd 100644 (file)
@@ -41,6 +41,7 @@
  * @TYPE_ICMPX_CODE:   icmpx code (integer subtype)
  * @TYPE_DEVGROUP:     devgroup code (integer subtype)
  * @TYPE_DSCP:         Differentiated Services Code Point (integer subtype)
+ * @TYPE_IFNAME:       interface name (string subtype)
  */
 enum datatypes {
        TYPE_INVALID,
@@ -84,6 +85,7 @@ enum datatypes {
        TYPE_FIB_ADDR,
        TYPE_BOOLEAN,
        TYPE_CT_EVENTBIT,
+       TYPE_IFNAME,
        __TYPE_MAX
 };
 #define TYPE_MAX               (__TYPE_MAX - 1)
index 47b16c4b7e82766913cd7470d2240d8ac110315a..6086a71cc0115923bc8b4e3ff4e58e8991788ea2 100644 (file)
@@ -38,5 +38,6 @@ extern const struct datatype gid_type;
 extern const struct datatype uid_type;
 extern const struct datatype devgroup_type;
 extern const struct datatype pkttype_type;
+extern const struct datatype ifname_type;
 
 #endif /* NFTABLES_META_H */
index 93726cafc98a1ca1d7610b3547ba8e01ba819ed1..324ac8022b9bcd89ceddff1c75ccebe47930fbd4 100644 (file)
@@ -68,6 +68,7 @@ static const struct datatype *datatypes[TYPE_MAX + 1] = {
        [TYPE_ECN]              = &ecn_type,
        [TYPE_FIB_ADDR]         = &fib_addr_type,
        [TYPE_BOOLEAN]          = &boolean_type,
+       [TYPE_IFNAME]           = &ifname_type,
 };
 
 const struct datatype *datatype_lookup(enum datatypes type)
index e5ad1044fbb7dd54f7a8c768988cdd034509adde..c98749d92a21a5238060779c093fabe922a036ab 100644 (file)
@@ -245,7 +245,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, ctx->ectx.dtype,
                                            BYTEORDER_HOST_ENDIAN,
                                            expr->len, data);
                expr_free(expr);
@@ -260,20 +260,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, ctx->ectx.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, ctx->ectx.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 = ctx->ectx.dtype;
        prefix->flags |= EXPR_F_CONSTANT;
        prefix->byteorder = BYTEORDER_HOST_ENDIAN;
 
@@ -1769,6 +1769,7 @@ static int expr_evaluate_meta(struct eval_ctx *ctx, struct expr **exprp)
            meta->meta.key == NFT_META_NFPROTO)
                return expr_error(ctx->msgs, meta,
                                          "meta nfproto is only useful in the inet family");
+
        return expr_evaluate_primary(ctx, exprp);
 }
 
index 8c2eca270e0dcce073630c471fa902ef72997d1a..11de2dab8b9be6cb588730f7ea7459d164f43306 100644 (file)
@@ -369,6 +369,15 @@ const struct datatype devgroup_type = {
        .flags          = DTYPE_F_PREFIX,
 };
 
+const struct datatype ifname_type = {
+       .type           = TYPE_IFNAME,
+       .name           = "ifname",
+       .desc           = "network interface name",
+       .byteorder      = BYTEORDER_HOST_ENDIAN,
+       .size           = IFNAMSIZ * BITS_PER_BYTE,
+       .basetype       = &string_type,
+};
+
 static const struct meta_template meta_templates[] = {
        [NFT_META_LEN]          = META_TEMPLATE("length",    &integer_type,
                                                4 * 8, BYTEORDER_HOST_ENDIAN),
@@ -384,14 +393,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,
@@ -404,10 +413,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,
index 622425ee10290c03ab1f931d801b70930043c773..a1f0e92310462856504c0ec926e95c81734ba15e 100644 (file)
@@ -271,9 +271,8 @@ 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) {
-               return netlink_error(ctx, loc,
-                                    "Relational expression size mismatch");
+           expr_basetype(left) != &string_type) {
+               return netlink_error(ctx, loc, "Relational expression size mismatch");
        } else if (left->len > 0 && left->len < right->len) {
                left = netlink_parse_concat_expr(ctx, loc, sreg, right->len);
                if (left == NULL)
@@ -1728,7 +1727,7 @@ static struct expr *string_wildcard_expr_alloc(struct location *loc,
        data[pos] = '*';
        data[pos + 1] = '\0';
 
-       return constant_expr_alloc(loc, &string_type, BYTEORDER_HOST_ENDIAN,
+       return constant_expr_alloc(loc, expr->dtype, BYTEORDER_HOST_ENDIAN,
                                   expr->len + BITS_PER_BYTE, data);
 }
 
@@ -1744,7 +1743,7 @@ static void escaped_string_wildcard_expr_alloc(struct expr **exprp,
        data[pos - 1] = '\\';
        data[pos] = '*';
 
-       tmp = constant_expr_alloc(&expr->location, &string_type,
+       tmp = constant_expr_alloc(&expr->location, expr->dtype,
                                  BYTEORDER_HOST_ENDIAN,
                                  expr->len + BITS_PER_BYTE, data);
        expr_free(expr);
@@ -1789,7 +1788,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;
 
@@ -1893,7 +1892,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 &&
index 99a4dde22adbd182e7b5eacc2a37892b015604eb..77abdcb8a23ee4b595a38d422e391faed04097a6 100644 (file)
@@ -364,7 +364,7 @@ static void netlink_gen_cmp(struct netlink_linearize_ctx *ctx,
                return netlink_gen_lookup(ctx, expr, dreg);
        case EXPR_PREFIX:
                sreg = get_register(ctx, expr->left);
-               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);
diff --git a/tests/shell/testcases/maps/0007named_ifname_dtype_0 b/tests/shell/testcases/maps/0007named_ifname_dtype_0
new file mode 100755 (executable)
index 0000000..dcbcf2f
--- /dev/null
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+# support for ifname in named maps
+
+tmpfile=$(mktemp)
+if [ ! -w $tmpfile ] ; then
+       echo "Failed to create tmp file" >&2
+       exit 0
+fi
+
+trap "rm -rf $tmpfile" EXIT # cleanup if aborted
+
+EXPECTED="table inet t {
+       map m1 {
+               type ifname : ipv4_addr
+               elements = { \"eth0\" : 1.1.1.1 }
+       }
+
+       chain c {
+               ip daddr set iifname map @m1
+               ip daddr set oifname map @m1
+       }
+}"
+
+set -e
+echo "$EXPECTED" > $tmpfile
+$NFT -f $tmpfile
+
+GET="$($NFT list ruleset)"
+if [ "$EXPECTED" != "$GET" ] ; then
+        DIFF="$(which diff)"
+        [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET")
+        exit 1
+fi
+
diff --git a/tests/shell/testcases/sets/0029named_ifname_dtype_0 b/tests/shell/testcases/sets/0029named_ifname_dtype_0
new file mode 100755 (executable)
index 0000000..8b7ab98
--- /dev/null
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+# support for ifname in named sets
+
+tmpfile=$(mktemp)
+if [ ! -w $tmpfile ] ; then
+       echo "Failed to create tmp file" >&2
+       exit 0
+fi
+
+trap "rm -rf $tmpfile" EXIT # cleanup if aborted
+
+EXPECTED="table inet t {
+       set s {
+               type ifname
+               elements = { \"eth0\" }
+       }
+
+       chain c {
+               iifname @s accept
+               oifname @s accept
+       }
+}"
+
+set -e
+echo "$EXPECTED" > $tmpfile
+$NFT -f $tmpfile
+
+GET="$($NFT list ruleset)"
+if [ "$EXPECTED" != "$GET" ] ; then
+        DIFF="$(which diff)"
+        [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET")
+        exit 1
+fi
+