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 e9486915eff6..7302b0b7b642 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; |
