diff options
author | Ulrich Weber <ulrich.weber@sophos.com> | 2013-01-02 00:24:40 -0500 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2013-01-04 14:03:02 -0500 |
commit | 429da4c0b1e59837ec946cdf0f04eb1899586923 (patch) | |
tree | a7b9ce4917c399fb7d67bd7e3132f70b35f536ac | |
parent | fdb184d1467f9ed5b17c553b85eb1bb72bdbf62f (diff) |
netfilter: ip6t_NPT: fix IPv6 NTP checksum calculation
csum16_add() has a broken carry detection, should be:
sum += sum < (__force u16)b;
Instead of fixing csum16_add, remove the custom checksum
functions and use the generic csum_add/csum_sub ones.
Signed-off-by: Ulrich Weber <ulrich.weber@sophos.com>
Acked-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r-- | net/ipv6/netfilter/ip6t_NPT.c | 33 |
1 files changed, 7 insertions, 26 deletions
diff --git a/net/ipv6/netfilter/ip6t_NPT.c b/net/ipv6/netfilter/ip6t_NPT.c index e9486915eff..7302b0b7b64 100644 --- a/net/ipv6/netfilter/ip6t_NPT.c +++ b/net/ipv6/netfilter/ip6t_NPT.c | |||
@@ -14,42 +14,23 @@ | |||
14 | #include <linux/netfilter_ipv6/ip6t_NPT.h> | 14 | #include <linux/netfilter_ipv6/ip6t_NPT.h> |
15 | #include <linux/netfilter/x_tables.h> | 15 | #include <linux/netfilter/x_tables.h> |
16 | 16 | ||
17 | static __sum16 csum16_complement(__sum16 a) | ||
18 | { | ||
19 | return (__force __sum16)(0xffff - (__force u16)a); | ||
20 | } | ||
21 | |||
22 | static __sum16 csum16_add(__sum16 a, __sum16 b) | ||
23 | { | ||
24 | u16 sum; | ||
25 | |||
26 | sum = (__force u16)a + (__force u16)b; | ||
27 | sum += (__force u16)a < (__force u16)b; | ||
28 | return (__force __sum16)sum; | ||
29 | } | ||
30 | |||
31 | static __sum16 csum16_sub(__sum16 a, __sum16 b) | ||
32 | { | ||
33 | return csum16_add(a, csum16_complement(b)); | ||
34 | } | ||
35 | |||
36 | static int ip6t_npt_checkentry(const struct xt_tgchk_param *par) | 17 | static int ip6t_npt_checkentry(const struct xt_tgchk_param *par) |
37 | { | 18 | { |
38 | struct ip6t_npt_tginfo *npt = par->targinfo; | 19 | struct ip6t_npt_tginfo *npt = par->targinfo; |
39 | __sum16 src_sum = 0, dst_sum = 0; | 20 | __wsum src_sum = 0, dst_sum = 0; |
40 | unsigned int i; | 21 | unsigned int i; |
41 | 22 | ||
42 | if (npt->src_pfx_len > 64 || npt->dst_pfx_len > 64) | 23 | if (npt->src_pfx_len > 64 || npt->dst_pfx_len > 64) |
43 | return -EINVAL; | 24 | return -EINVAL; |
44 | 25 | ||
45 | for (i = 0; i < ARRAY_SIZE(npt->src_pfx.in6.s6_addr16); i++) { | 26 | for (i = 0; i < ARRAY_SIZE(npt->src_pfx.in6.s6_addr16); i++) { |
46 | src_sum = csum16_add(src_sum, | 27 | src_sum = csum_add(src_sum, |
47 | (__force __sum16)npt->src_pfx.in6.s6_addr16[i]); | 28 | (__force __wsum)npt->src_pfx.in6.s6_addr16[i]); |
48 | dst_sum = csum16_add(dst_sum, | 29 | dst_sum = csum_add(dst_sum, |
49 | (__force __sum16)npt->dst_pfx.in6.s6_addr16[i]); | 30 | (__force __wsum)npt->dst_pfx.in6.s6_addr16[i]); |
50 | } | 31 | } |
51 | 32 | ||
52 | npt->adjustment = csum16_sub(src_sum, dst_sum); | 33 | npt->adjustment = (__force __sum16) csum_sub(src_sum, dst_sum); |
53 | return 0; | 34 | return 0; |
54 | } | 35 | } |
55 | 36 | ||
@@ -85,7 +66,7 @@ static bool ip6t_npt_map_pfx(const struct ip6t_npt_tginfo *npt, | |||
85 | return false; | 66 | return false; |
86 | } | 67 | } |
87 | 68 | ||
88 | sum = csum16_add((__force __sum16)addr->s6_addr16[idx], | 69 | sum = (__force __sum16) csum_add((__force __wsum)addr->s6_addr16[idx], |
89 | npt->adjustment); | 70 | npt->adjustment); |
90 | if (sum == CSUM_MANGLED_0) | 71 | if (sum == CSUM_MANGLED_0) |
91 | sum = 0; | 72 | sum = 0; |