]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
proto: use NFT_PAYLOAD_L4CSUM_PSEUDOHDR flag to mangle UDP checksum
authorPablo Neira Ayuso <pablo@netfilter.org>
Mon, 9 Sep 2024 10:48:33 +0000 (12:48 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 23 Jan 2025 00:35:37 +0000 (01:35 +0100)
commit f89abfb4068d31f7279cae298abf25e0c077d2d3 upstream.

There are two mechanisms to update the UDP checksum field:

 1) _CSUM_TYPE and _CSUM_OFFSET which specify the type of checksum
    (e.g. inet) and offset where it is located.
 2) use NFT_PAYLOAD_L4CSUM_PSEUDOHDR flag to use layer 4 kernel
    protocol parser.

The problem with 1) is that it is inconditional, that is, csum_type and
csum_offset cannot deal with zero UDP checksum.

Use NFT_PAYLOAD_L4CSUM_PSEUDOHDR flag instead since it relies on the
layer 4 kernel parser which skips updating zero UDP checksum.

Extend test coverage for the UDP mangling with and without zero
checksum.

Fixes: e6c9174e13b2 ("proto: add checksum key information to struct proto_desc")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/netlink_linearize.c
src/proto.c

index 1aaa12847cef8228f2de186efc9035db0bb18ce3..755ed58ebc5bcb38478f6c2c108b2b1dd6d5898f 100644 (file)
@@ -1032,6 +1032,8 @@ static void netlink_gen_payload_stmt(struct netlink_linearize_ctx *ctx,
        }
        if ((expr->payload.base == PROTO_BASE_NETWORK_HDR && desc &&
             payload_needs_l4csum_update_pseudohdr(expr, desc)) ||
+           (expr->payload.base == PROTO_BASE_TRANSPORT_HDR && desc &&
+            desc == &proto_udp) ||
            expr->payload.base == PROTO_BASE_INNER_HDR)
                nftnl_expr_set_u32(nle, NFTNL_EXPR_PAYLOAD_FLAGS,
                                   NFT_PAYLOAD_L4CSUM_PSEUDOHDR);
index 0f61b6595b6ad0eb5d666c634523f20605267618..baa003de574a4442b7319f1f61e32bafe6d8fdab 100644 (file)
@@ -507,8 +507,6 @@ const struct proto_desc proto_udp = {
        .name           = "udp",
        .id             = PROTO_DESC_UDP,
        .base           = PROTO_BASE_TRANSPORT_HDR,
-       .checksum_key   = UDPHDR_CHECKSUM,
-       .checksum_type  = NFT_PAYLOAD_CSUM_INET,
        .templates      = {
                [UDPHDR_SPORT]          = INET_SERVICE("sport", struct udphdr, source),
                [UDPHDR_DPORT]          = INET_SERVICE("dport", struct udphdr, dest),