diff options
author | YOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@linux-ipv6.org> | 2013-01-26 03:37:48 -0500 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2013-02-07 12:37:41 -0500 |
commit | f5271fff56c76e92fde122bcc02f102e99da5c8a (patch) | |
tree | 88e0f58ea00fbc4f8652f92d915b40403aa38f3e /net/ipv6 | |
parent | 4b47bc9a9e69141ed3a854c57601f548e82c78ba (diff) |
netfilter: ip6t_NPT: Fix adjustment calculation
Cast __wsum from/to __sum16 is wrong. Instead, apply appropriate
conversion function: csum_unfold() or csum_fold().
[ The original patch has been modified to undo the final ~ that
csum_fold returns. We only need to fold the 32-bit word that
results from the checksum calculation into a 16-bit to ensure
that the original subnet is restored appropriately. Spotted by
Ulrich Weber. ]
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/netfilter/ip6t_NPT.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/net/ipv6/netfilter/ip6t_NPT.c b/net/ipv6/netfilter/ip6t_NPT.c index 7302b0b7b642..68788c84aee7 100644 --- a/net/ipv6/netfilter/ip6t_NPT.c +++ b/net/ipv6/netfilter/ip6t_NPT.c | |||
@@ -30,7 +30,7 @@ static int ip6t_npt_checkentry(const struct xt_tgchk_param *par) | |||
30 | (__force __wsum)npt->dst_pfx.in6.s6_addr16[i]); | 30 | (__force __wsum)npt->dst_pfx.in6.s6_addr16[i]); |
31 | } | 31 | } |
32 | 32 | ||
33 | npt->adjustment = (__force __sum16) csum_sub(src_sum, dst_sum); | 33 | npt->adjustment = ~csum_fold(csum_sub(src_sum, dst_sum)); |
34 | return 0; | 34 | return 0; |
35 | } | 35 | } |
36 | 36 | ||
@@ -66,8 +66,8 @@ static bool ip6t_npt_map_pfx(const struct ip6t_npt_tginfo *npt, | |||
66 | return false; | 66 | return false; |
67 | } | 67 | } |
68 | 68 | ||
69 | sum = (__force __sum16) csum_add((__force __wsum)addr->s6_addr16[idx], | 69 | sum = ~csum_fold(csum_add(csum_unfold((__force __sum16)addr->s6_addr16[idx]), |
70 | npt->adjustment); | 70 | csum_unfold(npt->adjustment))); |
71 | if (sum == CSUM_MANGLED_0) | 71 | if (sum == CSUM_MANGLED_0) |
72 | sum = 0; | 72 | sum = 0; |
73 | *(__force __sum16 *)&addr->s6_addr16[idx] = sum; | 73 | *(__force __sum16 *)&addr->s6_addr16[idx] = sum; |