summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Sowden <jeremy@azazel.net>2021-12-11 18:55:25 +0000
committerPablo Neira Ayuso <pablo@netfilter.org>2021-12-15 22:50:07 +0100
commit0379244930035b3bff95281a58fa7efd7e50dd51 (patch)
treea6866a1c9ce58a5c76a43433b6c618e80a213894
parent368c8ba1bd9765d9ad225c63b40423c321ffd5d4 (diff)
evaluate: reject: support ethernet as L2 protocol for inet table
When we are evaluating a `reject` statement in the `inet` family, we may have `ether` and `ip` or `ip6` as the L2 and L3 protocols in the evaluation context: table inet filter { chain input { type filter hook input priority filter; ether saddr aa:bb:cc:dd:ee:ff ip daddr 192.168.0.1 reject } } Since no `reject` option is given, nft attempts to infer one and fails: BUG: unsupported familynft: evaluate.c:2766:stmt_evaluate_reject_inet_family: Assertion `0' failed. Aborted The reason it fails is that the ethernet protocol numbers for IPv4 and IPv6 (`ETH_P_IP` and `ETH_P_IPV6`) do not match `NFPROTO_IPV4` and `NFPROTO_IPV6`. Add support for the ethernet protocol numbers. Replace the current `BUG("unsupported family")` error message with something more informative that tells the user to provide an explicit reject option. Add a Python test case. Fixes: 5fdd0b6a0600 ("nft: complete reject support") Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1001360 Signed-off-by: Jeremy Sowden <jeremy@azazel.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--src/evaluate.c7
-rw-r--r--tests/py/inet/reject.t2
-rw-r--r--tests/py/inet/reject.t.json34
-rw-r--r--tests/py/inet/reject.t.payload.inet10
4 files changed, 52 insertions, 1 deletions
diff --git a/src/evaluate.c b/src/evaluate.c
index 4d4dcc2e..8edefbd1 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -2751,19 +2751,22 @@ static int stmt_evaluate_reject_inet_family(struct eval_ctx *ctx,
protocol = proto_find_num(base, desc);
switch (protocol) {
case NFPROTO_IPV4:
+ case __constant_htons(ETH_P_IP):
if (stmt->reject.family == NFPROTO_IPV4)
break;
return stmt_binary_error(ctx, stmt->reject.expr,
&ctx->pctx.protocol[PROTO_BASE_NETWORK_HDR],
"conflicting protocols specified: ip vs ip6");
case NFPROTO_IPV6:
+ case __constant_htons(ETH_P_IPV6):
if (stmt->reject.family == NFPROTO_IPV6)
break;
return stmt_binary_error(ctx, stmt->reject.expr,
&ctx->pctx.protocol[PROTO_BASE_NETWORK_HDR],
"conflicting protocols specified: ip vs ip6");
default:
- BUG("unsupported family");
+ return stmt_error(ctx, stmt,
+ "cannot infer ICMP reject variant to use: explicit value required.\n");
}
break;
}
@@ -2923,10 +2926,12 @@ static int stmt_evaluate_reject_default(struct eval_ctx *ctx,
protocol = proto_find_num(base, desc);
switch (protocol) {
case NFPROTO_IPV4:
+ case __constant_htons(ETH_P_IP):
stmt->reject.family = NFPROTO_IPV4;
stmt->reject.icmp_code = ICMP_PORT_UNREACH;
break;
case NFPROTO_IPV6:
+ case __constant_htons(ETH_P_IPV6):
stmt->reject.family = NFPROTO_IPV6;
stmt->reject.icmp_code = ICMP6_DST_UNREACH_NOPORT;
break;
diff --git a/tests/py/inet/reject.t b/tests/py/inet/reject.t
index 1c8aeebe..61a6d556 100644
--- a/tests/py/inet/reject.t
+++ b/tests/py/inet/reject.t
@@ -37,3 +37,5 @@ meta l4proto udp reject with tcp reset;fail
meta nfproto ipv4 reject with icmpx admin-prohibited;ok
meta nfproto ipv6 reject with icmpx admin-prohibited;ok
+
+ether saddr aa:bb:cc:dd:ee:ff ip daddr 192.168.0.1 reject;ok;ether saddr aa:bb:cc:dd:ee:ff ip daddr 192.168.0.1 reject with icmp port-unreachable
diff --git a/tests/py/inet/reject.t.json b/tests/py/inet/reject.t.json
index 76cd1bf5..02ac9007 100644
--- a/tests/py/inet/reject.t.json
+++ b/tests/py/inet/reject.t.json
@@ -295,3 +295,37 @@
}
]
+# ether saddr aa:bb:cc:dd:ee:ff ip daddr 192.168.0.1 reject
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "aa:bb:cc:dd:ee:ff"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "192.168.0.1"
+ }
+ },
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
diff --git a/tests/py/inet/reject.t.payload.inet b/tests/py/inet/reject.t.payload.inet
index 62078d91..828cb839 100644
--- a/tests/py/inet/reject.t.payload.inet
+++ b/tests/py/inet/reject.t.payload.inet
@@ -132,3 +132,13 @@ inet test-inet input
[ cmp eq reg 1 0x0000000a ]
[ reject type 2 code 3 ]
+# ether saddr aa:bb:cc:dd:ee:ff ip daddr 192.168.0.1 reject
+inet test-inet input
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 8b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0xddccbbaa 0x0008ffee ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x0100a8c0 ]
+ [ reject type 0 code 3 ]
+