summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArturo Borrero Gonzalez <arturo@netfilter.org>2018-02-25 18:30:24 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2018-02-25 23:09:02 +0100
commit8c61fa70f3cebed06b23292a3467f1dbc1b96ce9 (patch)
tree46f4550c256a590094c0e732077675d40a73051a
parentba00c6b18ee2bf3bc100226ecc2e6bfd779eb482 (diff)
meta: introduce datatype ifname_type
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>
-rw-r--r--doc/nft.xml8
-rw-r--r--include/datatype.h2
-rw-r--r--include/meta.h1
-rw-r--r--src/datatype.c1
-rw-r--r--src/evaluate.c9
-rw-r--r--src/meta.c17
-rw-r--r--src/netlink_delinearize.c13
-rw-r--r--src/netlink_linearize.c2
-rwxr-xr-xtests/shell/testcases/maps/0007named_ifname_dtype_035
-rwxr-xr-xtests/shell/testcases/sets/0029named_ifname_dtype_035
10 files changed, 103 insertions, 20 deletions
diff --git a/doc/nft.xml b/doc/nft.xml
index 9d21e9a1..6748265c 100644
--- a/doc/nft.xml
+++ b/doc/nft.xml
@@ -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>
diff --git a/include/datatype.h b/include/datatype.h
index cc4cb078..3f612e52 100644
--- a/include/datatype.h
+++ b/include/datatype.h
@@ -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)
diff --git a/include/meta.h b/include/meta.h
index 47b16c4b..6086a71c 100644
--- a/include/meta.h
+++ b/include/meta.h
@@ -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 */
diff --git a/src/datatype.c b/src/datatype.c
index 93726caf..324ac802 100644
--- a/src/datatype.c
+++ b/src/datatype.c
@@ -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)
diff --git a/src/evaluate.c b/src/evaluate.c
index e5ad1044..c98749d9 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -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);
}
diff --git a/src/meta.c b/src/meta.c
index 8c2eca27..11de2dab 100644
--- a/src/meta.c
+++ b/src/meta.c
@@ -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,
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 622425ee..a1f0e923 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -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 &&
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 99a4dde2..77abdcb8 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -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
index 00000000..dcbcf2f0
--- /dev/null
+++ b/tests/shell/testcases/maps/0007named_ifname_dtype_0
@@ -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
index 00000000..8b7ab982
--- /dev/null
+++ b/tests/shell/testcases/sets/0029named_ifname_dtype_0
@@ -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
+