From 422c346fad806e2abaeffac686860ebc98dfe33e Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 6 Apr 2006 14:18:43 -0700 Subject: [NETFILTER]: Add address family specific checksum helpers Add checksum operation which takes care of verifying the checksum and dealing with HW checksum errors and avoids multiple checksum operations by setting ip_summed to CHECKSUM_UNNECESSARY after successful verification. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv6/netfilter.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'net/ipv6/netfilter.c') diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index f514a0113b9f..3e9ecfaf67e2 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c @@ -79,8 +79,42 @@ static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info) return 0; } +unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, u_int8_t protocol) +{ + struct ipv6hdr *ip6h = skb->nh.ipv6h; + unsigned int csum = 0; + + switch (skb->ip_summed) { + case CHECKSUM_HW: + if (hook != NF_IP6_PRE_ROUTING && hook != NF_IP6_LOCAL_IN) + break; + if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, + skb->len - dataoff, protocol, + csum_sub(skb->csum, + skb_checksum(skb, 0, + dataoff, 0)))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + break; + } + /* fall through */ + case CHECKSUM_NONE: + skb->csum = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, + skb->len - dataoff, + protocol, + csum_sub(0, + skb_checksum(skb, 0, + dataoff, 0))); + csum = __skb_checksum_complete(skb); + } + return csum; +} + +EXPORT_SYMBOL(nf_ip6_checksum); + static struct nf_afinfo nf_ip6_afinfo = { .family = AF_INET6, + .checksum = nf_ip6_checksum, .saveroute = nf_ip6_saveroute, .reroute = nf_ip6_reroute, .route_key_size = sizeof(struct ip6_rt_info), -- cgit v1.2.3