diff options
-rw-r--r-- | src/netlink_delinearize.c | 83 | ||||
-rw-r--r-- | tests/py/inet/icmp.t | 18 | ||||
-rw-r--r-- | tests/py/inet/icmp.t.json | 114 | ||||
-rw-r--r-- | tests/py/inet/icmp.t.json.output | 30 | ||||
-rw-r--r-- | tests/py/inet/icmp.t.payload | 54 |
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 ] + |