Blob Blame Raw
From 876a1202351264f6d3b105258f10bde693870bd4 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 7 Dec 2020 18:27:16 +0100
Subject: [PATCH] proto: add sctp crc32 checksum fixup

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1895804
Upstream Status: nftables commit 09a3b2ba0c822

commit 09a3b2ba0c8228d1c6bf0f030cae97addb397351
Author: Florian Westphal <fw@strlen.de>
Date:   Tue Oct 6 23:16:32 2020 +0200

    proto: add sctp crc32 checksum fixup

    Stateless SCTP header mangling doesn't work reliably.
    This tells the kernel to update the checksum field using
    the sctp crc32 algorithm.

    Note that this needs additional kernel support to work.

    Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/linux/netfilter/nf_tables.h | 2 ++
 include/proto.h                     | 1 +
 src/netlink_linearize.c             | 2 +-
 src/proto.c                         | 8 ++++++++
 4 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 9b54a86..1328b8e 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -707,10 +707,12 @@ enum nft_payload_bases {
  *
  * @NFT_PAYLOAD_CSUM_NONE: no checksumming
  * @NFT_PAYLOAD_CSUM_INET: internet checksum (RFC 791)
+ * @NFT_PAYLOAD_CSUM_SCTP: CRC-32c, for use in SCTP header (RFC 3309)
  */
 enum nft_payload_csum_types {
 	NFT_PAYLOAD_CSUM_NONE,
 	NFT_PAYLOAD_CSUM_INET,
+	NFT_PAYLOAD_CSUM_SCTP,
 };
 
 enum nft_payload_csum_flags {
diff --git a/include/proto.h b/include/proto.h
index fab48c1..436cbe3 100644
--- a/include/proto.h
+++ b/include/proto.h
@@ -78,6 +78,7 @@ struct proto_hdr_template {
 struct proto_desc {
 	const char			*name;
 	enum proto_bases		base;
+	enum nft_payload_csum_types	checksum_type;
 	unsigned int			checksum_key;
 	unsigned int			protocol_key;
 	unsigned int			length;
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index cb1b7fe..606d97a 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -937,7 +937,7 @@ static void netlink_gen_payload_stmt(struct netlink_linearize_ctx *ctx,
 			   expr->len / BITS_PER_BYTE);
 	if (csum_off) {
 		nftnl_expr_set_u32(nle, NFTNL_EXPR_PAYLOAD_CSUM_TYPE,
-				   NFT_PAYLOAD_CSUM_INET);
+				   desc->checksum_type);
 		nftnl_expr_set_u32(nle, NFTNL_EXPR_PAYLOAD_CSUM_OFFSET,
 				   csum_off / BITS_PER_BYTE);
 	}
diff --git a/src/proto.c b/src/proto.c
index 40ce590..8360abf 100644
--- a/src/proto.c
+++ b/src/proto.c
@@ -345,6 +345,7 @@ const struct proto_desc proto_icmp = {
 	.name		= "icmp",
 	.base		= PROTO_BASE_TRANSPORT_HDR,
 	.checksum_key	= ICMPHDR_CHECKSUM,
+	.checksum_type  = NFT_PAYLOAD_CSUM_INET,
 	.templates	= {
 		[ICMPHDR_TYPE]		= ICMPHDR_TYPE("type", &icmp_type_type, type),
 		[ICMPHDR_CODE]		= ICMPHDR_TYPE("code", &icmp_code_type, code),
@@ -397,6 +398,7 @@ const struct proto_desc proto_igmp = {
 	.name		= "igmp",
 	.base		= PROTO_BASE_TRANSPORT_HDR,
 	.checksum_key	= IGMPHDR_CHECKSUM,
+	.checksum_type  = NFT_PAYLOAD_CSUM_INET,
 	.templates	= {
 		[IGMPHDR_TYPE]		= IGMPHDR_TYPE("type", &igmp_type_type, igmp_type),
 		[IGMPHDR_MRT]		= IGMPHDR_FIELD("mrt", igmp_code),
@@ -417,6 +419,7 @@ const struct proto_desc proto_udp = {
 	.name		= "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),
@@ -474,6 +477,7 @@ const struct proto_desc proto_tcp = {
 	.name		= "tcp",
 	.base		= PROTO_BASE_TRANSPORT_HDR,
 	.checksum_key	= TCPHDR_CHECKSUM,
+	.checksum_type  = NFT_PAYLOAD_CSUM_INET,
 	.templates	= {
 		[TCPHDR_SPORT]		= INET_SERVICE("sport", struct tcphdr, source),
 		[TCPHDR_DPORT]		= INET_SERVICE("dport", struct tcphdr, dest),
@@ -553,6 +557,8 @@ const struct proto_desc proto_dccp = {
 const struct proto_desc proto_sctp = {
 	.name		= "sctp",
 	.base		= PROTO_BASE_TRANSPORT_HDR,
+	.checksum_key	= SCTPHDR_CHECKSUM,
+	.checksum_type  = NFT_PAYLOAD_CSUM_SCTP,
 	.templates	= {
 		[SCTPHDR_SPORT]		= INET_SERVICE("sport", struct sctphdr, source),
 		[SCTPHDR_DPORT]		= INET_SERVICE("dport", struct sctphdr, dest),
@@ -650,6 +656,7 @@ const struct proto_desc proto_ip = {
 	.name		= "ip",
 	.base		= PROTO_BASE_NETWORK_HDR,
 	.checksum_key	= IPHDR_CHECKSUM,
+	.checksum_type  = NFT_PAYLOAD_CSUM_INET,
 	.protocols	= {
 		PROTO_LINK(IPPROTO_ICMP,	&proto_icmp),
 		PROTO_LINK(IPPROTO_IGMP,	&proto_igmp),
@@ -746,6 +753,7 @@ const struct proto_desc proto_icmp6 = {
 	.name		= "icmpv6",
 	.base		= PROTO_BASE_TRANSPORT_HDR,
 	.checksum_key	= ICMP6HDR_CHECKSUM,
+	.checksum_type  = NFT_PAYLOAD_CSUM_INET,
 	.templates	= {
 		[ICMP6HDR_TYPE]		= ICMP6HDR_TYPE("type", &icmp6_type_type, icmp6_type),
 		[ICMP6HDR_CODE]		= ICMP6HDR_TYPE("code", &icmpv6_code_type, icmp6_code),
-- 
1.8.3.1