summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/netlink_delinearize.c83
-rw-r--r--tests/py/inet/icmp.t18
-rw-r--r--tests/py/inet/icmp.t.json114
-rw-r--r--tests/py/inet/icmp.t.json.output30
-rw-r--r--tests/py/inet/icmp.t.payload54
5 files changed, 259 insertions, 40 deletions
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 31d62420..7e9765cf 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -1522,61 +1522,64 @@ static bool meta_may_dependency_kill(struct payload_dep_ctx *ctx,
const struct expr *expr)
{
struct expr *dep = ctx->pdep->expr;
+ uint16_t l3proto;
+ uint8_t l4proto;
if (ctx->pbase != PROTO_BASE_NETWORK_HDR)
return true;
switch (family) {
case NFPROTO_INET:
- switch (dep->left->ops->type) {
- case EXPR_META:
- if (dep->left->meta.key == NFT_META_NFPROTO &&
- (mpz_get_uint16(dep->right->value) == NFPROTO_IPV4 ||
- mpz_get_uint16(dep->right->value) == NFPROTO_IPV6) &&
- expr->left->meta.key == NFT_META_L4PROTO &&
- mpz_get_uint8(expr->right->value) != IPPROTO_ICMP &&
- mpz_get_uint8(expr->right->value) != IPPROTO_ICMPV6)
- return false;
- break;
- case EXPR_PAYLOAD:
- if (dep->left->payload.base == PROTO_BASE_LL_HDR &&
- (mpz_get_uint16(dep->right->value) == ETH_P_IP ||
- mpz_get_uint16(dep->right->value) == ETH_P_IPV6) &&
- expr->left->meta.key == NFT_META_L4PROTO &&
- mpz_get_uint8(expr->right->value) != IPPROTO_ICMP &&
- mpz_get_uint8(expr->right->value) != IPPROTO_ICMPV6)
- return false;
- break;
- default:
- break;
- }
- break;
case NFPROTO_NETDEV:
case NFPROTO_BRIDGE:
- switch (dep->left->ops->type) {
- case EXPR_META:
- if (dep->left->meta.key == NFT_META_PROTOCOL &&
- (mpz_get_uint16(dep->right->value) == ETH_P_IP ||
- mpz_get_uint16(dep->right->value) == ETH_P_IPV6) &&
- expr->left->meta.key == NFT_META_L4PROTO &&
- mpz_get_uint8(expr->right->value) != IPPROTO_ICMP &&
- mpz_get_uint8(expr->right->value) != IPPROTO_ICMPV6)
- return false;
+ break;
+ default:
+ return true;
+ }
+
+ if (expr->left->meta.key != NFT_META_L4PROTO)
+ return true;
+
+ l3proto = mpz_get_uint16(dep->right->value);
+
+ switch (dep->left->ops->type) {
+ case EXPR_META:
+ if (dep->left->meta.key != NFT_META_NFPROTO)
+ return true;
+ break;
+ case EXPR_PAYLOAD:
+ if (dep->left->payload.base != PROTO_BASE_LL_HDR)
+ return true;
+
+ switch(l3proto) {
+ case ETH_P_IP:
+ l3proto = NFPROTO_IPV4;
break;
- case EXPR_PAYLOAD:
- if (dep->left->payload.base == PROTO_BASE_LL_HDR &&
- (mpz_get_uint16(dep->right->value) == ETH_P_IP ||
- mpz_get_uint16(dep->right->value) == ETH_P_IPV6) &&
- expr->left->meta.key == NFT_META_L4PROTO &&
- mpz_get_uint8(expr->right->value) != IPPROTO_ICMP &&
- mpz_get_uint8(expr->right->value) != IPPROTO_ICMPV6)
- return false;
+ case ETH_P_IPV6:
+ l3proto = NFPROTO_IPV6;
break;
default:
break;
}
break;
+ default:
+ break;
+ }
+
+ l4proto = mpz_get_uint8(expr->right->value);
+
+ switch (l4proto) {
+ case IPPROTO_ICMP:
+ case IPPROTO_ICMPV6:
+ break;
+ default:
+ return false;
}
+
+ if ((l3proto == NFPROTO_IPV4 && l4proto == IPPROTO_ICMPV6) ||
+ (l3proto == NFPROTO_IPV6 && l4proto == IPPROTO_ICMP))
+ return false;
+
return true;
}
diff --git a/tests/py/inet/icmp.t b/tests/py/inet/icmp.t
new file mode 100644
index 00000000..9014f846
--- /dev/null
+++ b/tests/py/inet/icmp.t
@@ -0,0 +1,18 @@
+:output;type filter hook output priority 0
+
+*inet;test-inet;output
+
+# without nfproto specified, these should add an implicit dependency on
+# the likely l3 proto (i.e., IPv6 for icmpv6 and IPv4 for icmp)
+
+icmp type echo-request;ok
+icmpv6 type echo-request;ok
+
+# make sure only those nfproto matches are dropped if
+# the next statement would add it as a dependency anyway
+
+meta nfproto ipv4 icmp type echo-request;ok;icmp type echo-request
+meta nfproto ipv4 icmpv6 type echo-request;ok
+
+meta nfproto ipv6 icmp type echo-request;ok
+meta nfproto ipv6 icmpv6 type echo-request;ok;icmpv6 type echo-request
diff --git a/tests/py/inet/icmp.t.json b/tests/py/inet/icmp.t.json
new file mode 100644
index 00000000..c4517605
--- /dev/null
+++ b/tests/py/inet/icmp.t.json
@@ -0,0 +1,114 @@
+# icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
+# icmpv6 type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmpv6"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
+# meta nfproto ipv4 icmp type echo-request
+[
+ {
+ "match": {
+ "left": { "meta": "nfproto" },
+ "right": "ipv4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
+# meta nfproto ipv4 icmpv6 type echo-request
+[
+ {
+ "match": {
+ "left": { "meta": "nfproto" },
+ "right": "ipv4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmpv6"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
+# meta nfproto ipv6 icmp type echo-request
+[
+ {
+ "match": {
+ "left": { "meta": "nfproto" },
+ "right": "ipv6"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
+# meta nfproto ipv6 icmpv6 type echo-request
+[
+ {
+ "match": {
+ "left": { "meta": "nfproto" },
+ "right": "ipv6"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmpv6"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
diff --git a/tests/py/inet/icmp.t.json.output b/tests/py/inet/icmp.t.json.output
new file mode 100644
index 00000000..2282900d
--- /dev/null
+++ b/tests/py/inet/icmp.t.json.output
@@ -0,0 +1,30 @@
+# meta nfproto ipv4 icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
+# meta nfproto ipv6 icmpv6 type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmpv6"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
diff --git a/tests/py/inet/icmp.t.payload b/tests/py/inet/icmp.t.payload
new file mode 100644
index 00000000..f98cfc39
--- /dev/null
+++ b/tests/py/inet/icmp.t.payload
@@ -0,0 +1,54 @@
+# icmp type echo-request
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# icmpv6 type echo-request
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000080 ]
+
+# meta nfproto ipv4 icmp type echo-request
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# meta nfproto ipv4 icmpv6 type echo-request
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000080 ]
+
+# meta nfproto ipv6 icmp type echo-request
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# meta nfproto ipv6 icmpv6 type echo-request
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000080 ]
+