All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mathias Koehrer <mathias.koehrer@etas.com>
To: Pablo Neira Ayuso <pablo@netfilter.org>
Cc: netfilter@vger.kernel.org
Subject: Re: netfilter-queue: Incorrect UDP checksum computation in nfq_udp_compute_checksum_ipv4
Date: Fri, 1 Apr 2016 13:34:56 +0200	[thread overview]
Message-ID: <56FE5CE0.9050604@etas.com> (raw)
In-Reply-To: <20160401104431.GA1318@salvia>

Hi Pablo,

>> the function nfq_udp_compute_checksum_ipv4 (src/extra/udp.c) does not
>> compute the correct UDP checksum.
>> The issue is caused by the called function checksum_tcpudp_ipv4()
>> (src/extra/checksum.c) that uses the hard coded protocol id IPPROTO_TCP
>> which is fine for TCP but fails for UDP.
>> A possible solution might be to pass the protocol id (IPPROTO_TCP /
>> IPPROTOC_UDP) as parameter to the function checksum_tcpudp_ipv4().
>>
>> The very same is also true for the IPv6 versions of these functions.
>>
>> Any feedback is welcome.
>
> Would you send us a patch to fix this? Thanks!
Here it is:

Regards

Mathias

Correct the computation of the UDP checksum
Index: libnetfilter_queue-1.0.2/src/extra/checksum.c
===================================================================
--- libnetfilter_queue-1.0.2.orig/src/extra/checksum.c
+++ libnetfilter_queue-1.0.2/src/extra/checksum.c
@@ -35,7 +35,7 @@ uint16_t checksum(uint32_t sum, uint16_t
 	return (uint16_t)(~sum);
 }
 
-uint16_t checksum_tcpudp_ipv4(struct iphdr *iph)
+uint16_t checksum_tcpudp_ipv4(struct iphdr *iph, uint16_t protocol_id)
 {
 	uint32_t sum = 0;
 	uint32_t iph_len = iph->ihl*4;
@@ -46,13 +46,13 @@ uint16_t checksum_tcpudp_ipv4(struct iph
 	sum += (iph->saddr) & 0xFFFF;
 	sum += (iph->daddr >> 16) & 0xFFFF;
 	sum += (iph->daddr) & 0xFFFF;
-	sum += htons(IPPROTO_TCP);
+	sum += htons(protocol_id);
 	sum += htons(len);
 
 	return checksum(sum, (uint16_t *)payload, len);
 }
 
-uint16_t checksum_tcpudp_ipv6(struct ip6_hdr *ip6h, void *transport_hdr)
+uint16_t checksum_tcpudp_ipv6(struct ip6_hdr *ip6h, void *transport_hdr, uint16_t protocol_id)
 {
 	uint32_t sum = 0;
 	uint32_t hdr_len = (uint32_t *)transport_hdr - (uint32_t *)ip6h;
@@ -68,7 +68,7 @@ uint16_t checksum_tcpudp_ipv6(struct ip6
 		sum += (ip6h->ip6_dst.s6_addr16[i] >> 16) & 0xFFFF;
 		sum += (ip6h->ip6_dst.s6_addr16[i]) & 0xFFFF;
 	}
-	sum += htons(IPPROTO_TCP);
+	sum += htons(protocol_id);
 	sum += htons(ip6h->ip6_plen);
 
 	return checksum(sum, (uint16_t *)payload, len);
Index: libnetfilter_queue-1.0.2/src/extra/tcp.c
===================================================================
--- libnetfilter_queue-1.0.2.orig/src/extra/tcp.c
+++ libnetfilter_queue-1.0.2/src/extra/tcp.c
@@ -91,7 +91,7 @@ nfq_tcp_compute_checksum_ipv4(struct tcp
 {
 	/* checksum field in header needs to be zero for calculation. */
 	tcph->check = 0;
-	tcph->check = checksum_tcpudp_ipv4(iph);
+	tcph->check = checksum_tcpudp_ipv4(iph, IPPROTO_TCP);
 }
 EXPORT_SYMBOL(nfq_tcp_compute_checksum_ipv4);
 
@@ -105,7 +105,7 @@ nfq_tcp_compute_checksum_ipv6(struct tcp
 {
 	/* checksum field in header needs to be zero for calculation. */
 	tcph->check = 0;
-	tcph->check = checksum_tcpudp_ipv6(ip6h, tcph);
+	tcph->check = checksum_tcpudp_ipv6(ip6h, tcph, IPPROTO_TCP);
 }
 EXPORT_SYMBOL(nfq_tcp_compute_checksum_ipv6);
 
Index: libnetfilter_queue-1.0.2/src/extra/udp.c
===================================================================
--- libnetfilter_queue-1.0.2.orig/src/extra/udp.c
+++ libnetfilter_queue-1.0.2/src/extra/udp.c
@@ -91,7 +91,7 @@ nfq_udp_compute_checksum_ipv4(struct udp
 {
 	/* checksum field in header needs to be zero for calculation. */
 	udph->check = 0;
-	udph->check = checksum_tcpudp_ipv4(iph);
+	udph->check = checksum_tcpudp_ipv4(iph, IPPROTO_UDP);
 }
 EXPORT_SYMBOL(nfq_udp_compute_checksum_ipv4);
 
@@ -110,7 +110,7 @@ nfq_udp_compute_checksum_ipv6(struct udp
 {
 	/* checksum field in header needs to be zero for calculation. */
 	udph->check = 0;
-	udph->check = checksum_tcpudp_ipv6(ip6h, udph);
+	udph->check = checksum_tcpudp_ipv6(ip6h, udph, IPPROTO_UDP);
 }
 EXPORT_SYMBOL(nfq_udp_compute_checksum_ipv6);
 
Index: libnetfilter_queue-1.0.2/src/internal.h
===================================================================
--- libnetfilter_queue-1.0.2.orig/src/internal.h
+++ libnetfilter_queue-1.0.2/src/internal.h
@@ -13,8 +13,8 @@ struct iphdr;
 struct ip6_hdr;
 
 uint16_t checksum(uint32_t sum, uint16_t *buf, int size);
-uint16_t checksum_tcpudp_ipv4(struct iphdr *iph);
-uint16_t checksum_tcpudp_ipv6(struct ip6_hdr *ip6h, void *transport_hdr);
+uint16_t checksum_tcpudp_ipv4(struct iphdr *iph, uint16_t protocol_id);
+uint16_t checksum_tcpudp_ipv6(struct ip6_hdr *ip6h, void *transport_hdr, uint16_t protocol_id);
 
 struct pkt_buff {
 	uint8_t *mac_header;


  reply	other threads:[~2016-04-01 11:34 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-01  8:48 netfilter-queue: Incorrect UDP checksum computation in nfq_udp_compute_checksum_ipv4 Mathias Koehrer
2016-04-01 10:44 ` Pablo Neira Ayuso
2016-04-01 11:34   ` Mathias Koehrer [this message]
2016-04-01 11:39     ` Mathias Koehrer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=56FE5CE0.9050604@etas.com \
    --to=mathias.koehrer@etas.com \
    --cc=netfilter@vger.kernel.org \
    --cc=pablo@netfilter.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.