diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2019-09-30 16:25:42 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2019-09-30 16:26:29 +0200 |
commit | 38a7e5b365edce1fc0a972a05bbda0673ca63cad (patch) | |
tree | bd7568505a14739910dc8c09faaeffde2bac869b /src/extra/checksum.c | |
parent | 601abd1c71ccdf90753cf294c120ad43fb25dc54 (diff) |
checksum: Fix UDP checksum calculation
The level 4 protocol is part of the UDP and TCP calculations.
nfq_checksum_tcpudp_ipv4() was using IPPROTO_TCP in this calculation,
which gave the wrong answer for UDP.
Based on patch from Alin Nastac, and patch description from Duncan Roe.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/extra/checksum.c')
-rw-r--r-- | src/extra/checksum.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/src/extra/checksum.c b/src/extra/checksum.c index f367f75..4d52a99 100644 --- a/src/extra/checksum.c +++ b/src/extra/checksum.c @@ -35,7 +35,7 @@ uint16_t nfq_checksum(uint32_t sum, uint16_t *buf, int size) return (uint16_t)(~sum); } -uint16_t nfq_checksum_tcpudp_ipv4(struct iphdr *iph) +uint16_t nfq_checksum_tcpudp_ipv4(struct iphdr *iph, uint16_t protonum) { uint32_t sum = 0; uint32_t iph_len = iph->ihl*4; @@ -46,13 +46,14 @@ uint16_t nfq_checksum_tcpudp_ipv4(struct iphdr *iph) sum += (iph->saddr) & 0xFFFF; sum += (iph->daddr >> 16) & 0xFFFF; sum += (iph->daddr) & 0xFFFF; - sum += htons(IPPROTO_TCP); + sum += htons(protonum); sum += htons(len); return nfq_checksum(sum, (uint16_t *)payload, len); } -uint16_t nfq_checksum_tcpudp_ipv6(struct ip6_hdr *ip6h, void *transport_hdr) +uint16_t nfq_checksum_tcpudp_ipv6(struct ip6_hdr *ip6h, void *transport_hdr, + uint16_t protonum) { uint32_t sum = 0; uint32_t hdr_len = (uint32_t *)transport_hdr - (uint32_t *)ip6h; @@ -68,7 +69,7 @@ uint16_t nfq_checksum_tcpudp_ipv6(struct ip6_hdr *ip6h, void *transport_hdr) sum += (ip6h->ip6_dst.s6_addr16[i] >> 16) & 0xFFFF; sum += (ip6h->ip6_dst.s6_addr16[i]) & 0xFFFF; } - sum += htons(IPPROTO_TCP); + sum += htons(protonum); sum += htons(ip6h->ip6_plen); return nfq_checksum(sum, (uint16_t *)payload, len); |