]> err.no Git - linux-2.6/blobdiff - net/ipv4/netfilter.c
Merge master.kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog
[linux-2.6] / net / ipv4 / netfilter.c
index b25339c11ea04cdebb2944c632255fcd67793506..6a9e34b794bc7d3c495566045ef2c38bad3a0c5d 100644 (file)
@@ -161,8 +161,41 @@ static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info)
        return 0;
 }
 
+unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
+                           unsigned int dataoff, u_int8_t protocol)
+{
+       struct iphdr *iph = skb->nh.iph;
+       unsigned int csum = 0;
+
+       switch (skb->ip_summed) {
+       case CHECKSUM_HW:
+               if (hook != NF_IP_PRE_ROUTING && hook != NF_IP_LOCAL_IN)
+                       break;
+               if ((protocol == 0 && !(u16)csum_fold(skb->csum)) ||
+                   !csum_tcpudp_magic(iph->saddr, iph->daddr,
+                                      skb->len - dataoff, protocol,
+                                      skb->csum)) {
+                       skb->ip_summed = CHECKSUM_UNNECESSARY;
+                       break;
+               }
+               /* fall through */
+       case CHECKSUM_NONE:
+               if (protocol == 0)
+                       skb->csum = 0;
+               else
+                       skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
+                                                      skb->len - dataoff,
+                                                      protocol, 0);
+               csum = __skb_checksum_complete(skb);
+       }
+       return csum;
+}
+
+EXPORT_SYMBOL(nf_ip_checksum);
+
 static struct nf_afinfo nf_ip_afinfo = {
        .family         = AF_INET,
+       .checksum       = nf_ip_checksum,
        .saveroute      = nf_ip_saveroute,
        .reroute        = nf_ip_reroute,
        .route_key_size = sizeof(struct ip_rt_info),