From 056aaa3e6dc65aced5e552233ac3e7f89fb81f86 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 21 Jun 2018 14:01:13 +0200 Subject: netlink_delinearize: Refactor meta_may_dependency_kill() The original intent was to fix a bug: The following rule in inet table: | meta nfproto ipv4 icmpv6 type echo-reply Was added correctly but when printing the meta match was falsely removed. The fix is to deny dependency killing if RHS family of nfproto match doesn't match RHS family of l4proto match. Adding this to the already large conditional led to even more unreadable code, therefore this patch tries to clean that up (and also removes the partial code duplication. Signed-off-by: Phil Sutter Signed-off-by: Florian Westphal --- src/netlink_delinearize.c | 83 ++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 40 deletions(-) (limited to 'src') 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; } -- cgit v1.2.3