net: Fix skb->csum update in inet_proto_csum_replace16().
skb->csum is updated incorrectly, when manipulation for NF_NAT_MANIP_SRC\DST is done on IPV6 packet. Fix: There is no need to update skb->csum in inet_proto_csum_replace16(), because update in two fields a.) IPv6 src/dst address and b.) L4 header checksum cancels each other for skb->csum calculation. Whereas inet_proto_csum_replace4 function needs to update skb->csum, because update in 3 fields a.) IPv4 src/dst address, b.) IPv4 Header checksum and c.) L4 header checksum results in same diff as L4 Header checksum for skb->csum calculation. [ pablo@netfilter.org: a few comestic documentation edits ] Signed-off-by: Praveen Chaudhary <pchaudhary@linkedin.com> Signed-off-by: Zhenggen Xu <zxu@linkedin.com> Signed-off-by: Andy Stracner <astracner@linkedin.com> Reviewed-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
eb014de4fd
commit
189c9b1e94
|
@ -438,6 +438,23 @@ void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,
|
|||
}
|
||||
EXPORT_SYMBOL(inet_proto_csum_replace4);
|
||||
|
||||
/**
|
||||
* inet_proto_csum_replace16 - update layer 4 header checksum field
|
||||
* @sum: Layer 4 header checksum field
|
||||
* @skb: sk_buff for the packet
|
||||
* @from: old IPv6 address
|
||||
* @to: new IPv6 address
|
||||
* @pseudohdr: True if layer 4 header checksum includes pseudoheader
|
||||
*
|
||||
* Update layer 4 header as per the update in IPv6 src/dst address.
|
||||
*
|
||||
* There is no need to update skb->csum in this function, because update in two
|
||||
* fields a.) IPv6 src/dst address and b.) L4 header checksum cancels each other
|
||||
* for skb->csum calculation. Whereas inet_proto_csum_replace4 function needs to
|
||||
* update skb->csum, because update in 3 fields a.) IPv4 src/dst address,
|
||||
* b.) IPv4 Header checksum and c.) L4 header checksum results in same diff as
|
||||
* L4 Header checksum for skb->csum calculation.
|
||||
*/
|
||||
void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
|
||||
const __be32 *from, const __be32 *to,
|
||||
bool pseudohdr)
|
||||
|
@ -449,9 +466,6 @@ void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
|
|||
if (skb->ip_summed != CHECKSUM_PARTIAL) {
|
||||
*sum = csum_fold(csum_partial(diff, sizeof(diff),
|
||||
~csum_unfold(*sum)));
|
||||
if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
|
||||
skb->csum = ~csum_partial(diff, sizeof(diff),
|
||||
~skb->csum);
|
||||
} else if (pseudohdr)
|
||||
*sum = ~csum_fold(csum_partial(diff, sizeof(diff),
|
||||
csum_unfold(*sum)));
|
||||
|
|
Loading…
Reference in New Issue