mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 20:51:03 +02:00
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:
committed by
Pablo Neira Ayuso
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);
|
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,
|
void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
|
||||||
const __be32 *from, const __be32 *to,
|
const __be32 *from, const __be32 *to,
|
||||||
bool pseudohdr)
|
bool pseudohdr)
|
||||||
@@ -449,9 +466,6 @@ void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
|
|||||||
if (skb->ip_summed != CHECKSUM_PARTIAL) {
|
if (skb->ip_summed != CHECKSUM_PARTIAL) {
|
||||||
*sum = csum_fold(csum_partial(diff, sizeof(diff),
|
*sum = csum_fold(csum_partial(diff, sizeof(diff),
|
||||||
~csum_unfold(*sum)));
|
~csum_unfold(*sum)));
|
||||||
if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
|
|
||||||
skb->csum = ~csum_partial(diff, sizeof(diff),
|
|
||||||
~skb->csum);
|
|
||||||
} else if (pseudohdr)
|
} else if (pseudohdr)
|
||||||
*sum = ~csum_fold(csum_partial(diff, sizeof(diff),
|
*sum = ~csum_fold(csum_partial(diff, sizeof(diff),
|
||||||
csum_unfold(*sum)));
|
csum_unfold(*sum)));
|
||||||
|
Reference in New Issue
Block a user