|
@@ -182,21 +182,44 @@ __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
|
|
}
|
|
}
|
|
return csum;
|
|
return csum;
|
|
}
|
|
}
|
|
-
|
|
|
|
EXPORT_SYMBOL(nf_ip_checksum);
|
|
EXPORT_SYMBOL(nf_ip_checksum);
|
|
|
|
|
|
|
|
+static __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook,
|
|
|
|
+ unsigned int dataoff, unsigned int len,
|
|
|
|
+ u_int8_t protocol)
|
|
|
|
+{
|
|
|
|
+ const struct iphdr *iph = ip_hdr(skb);
|
|
|
|
+ __sum16 csum = 0;
|
|
|
|
+
|
|
|
|
+ switch (skb->ip_summed) {
|
|
|
|
+ case CHECKSUM_COMPLETE:
|
|
|
|
+ if (len == skb->len - dataoff)
|
|
|
|
+ return nf_ip_checksum(skb, hook, dataoff, protocol);
|
|
|
|
+ /* fall through */
|
|
|
|
+ case CHECKSUM_NONE:
|
|
|
|
+ skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr, protocol,
|
|
|
|
+ skb->len - dataoff, 0);
|
|
|
|
+ skb->ip_summed = CHECKSUM_NONE;
|
|
|
|
+ csum = __skb_checksum_complete_head(skb, dataoff + len);
|
|
|
|
+ if (!csum)
|
|
|
|
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
|
|
|
|
+ }
|
|
|
|
+ return csum;
|
|
|
|
+}
|
|
|
|
+
|
|
static int nf_ip_route(struct dst_entry **dst, struct flowi *fl)
|
|
static int nf_ip_route(struct dst_entry **dst, struct flowi *fl)
|
|
{
|
|
{
|
|
return ip_route_output_key(&init_net, (struct rtable **)dst, fl);
|
|
return ip_route_output_key(&init_net, (struct rtable **)dst, fl);
|
|
}
|
|
}
|
|
|
|
|
|
static const struct nf_afinfo nf_ip_afinfo = {
|
|
static const struct nf_afinfo nf_ip_afinfo = {
|
|
- .family = AF_INET,
|
|
|
|
- .checksum = nf_ip_checksum,
|
|
|
|
- .route = nf_ip_route,
|
|
|
|
- .saveroute = nf_ip_saveroute,
|
|
|
|
- .reroute = nf_ip_reroute,
|
|
|
|
- .route_key_size = sizeof(struct ip_rt_info),
|
|
|
|
|
|
+ .family = AF_INET,
|
|
|
|
+ .checksum = nf_ip_checksum,
|
|
|
|
+ .checksum_partial = nf_ip_checksum_partial,
|
|
|
|
+ .route = nf_ip_route,
|
|
|
|
+ .saveroute = nf_ip_saveroute,
|
|
|
|
+ .reroute = nf_ip_reroute,
|
|
|
|
+ .route_key_size = sizeof(struct ip_rt_info),
|
|
};
|
|
};
|
|
|
|
|
|
static int ipv4_netfilter_init(void)
|
|
static int ipv4_netfilter_init(void)
|