|
@@ -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),
|