aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2008-03-20 10:15:53 -0400
committerPatrick McHardy <kaber@trash.net>2008-04-14 05:15:49 -0400
commitd63a650736f566a1f9e9434725d2089597c0d2cc (patch)
treef0a3d5dbc9ced46f95582e4133b55bb70a1ae365 /net/ipv4
parent6185f870e293a0a3eae5c81eb0106480cf03dfde (diff)
[NETFILTER]: Add partial checksum validation helper
Move the UDP-Lite conntrack checksum validation to a generic helper similar to nf_checksum() and make it fall back to nf_checksum() in case the full packet is to be checksummed and hardware checksums are available. This is to be used by DCCP conntrack, which also needs to verify partial checksums. Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/netfilter.c37
1 files changed, 30 insertions, 7 deletions
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index 9a904c6c0dc8..f8edacdf991d 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -182,21 +182,44 @@ __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
182 } 182 }
183 return csum; 183 return csum;
184} 184}
185
186EXPORT_SYMBOL(nf_ip_checksum); 185EXPORT_SYMBOL(nf_ip_checksum);
187 186
187static __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook,
188 unsigned int dataoff, unsigned int len,
189 u_int8_t protocol)
190{
191 const struct iphdr *iph = ip_hdr(skb);
192 __sum16 csum = 0;
193
194 switch (skb->ip_summed) {
195 case CHECKSUM_COMPLETE:
196 if (len == skb->len - dataoff)
197 return nf_ip_checksum(skb, hook, dataoff, protocol);
198 /* fall through */
199 case CHECKSUM_NONE:
200 skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr, protocol,
201 skb->len - dataoff, 0);
202 skb->ip_summed = CHECKSUM_NONE;
203 csum = __skb_checksum_complete_head(skb, dataoff + len);
204 if (!csum)
205 skb->ip_summed = CHECKSUM_UNNECESSARY;
206 }
207 return csum;
208}
209
188static int nf_ip_route(struct dst_entry **dst, struct flowi *fl) 210static int nf_ip_route(struct dst_entry **dst, struct flowi *fl)
189{ 211{
190 return ip_route_output_key(&init_net, (struct rtable **)dst, fl); 212 return ip_route_output_key(&init_net, (struct rtable **)dst, fl);
191} 213}
192 214
193static const struct nf_afinfo nf_ip_afinfo = { 215static const struct nf_afinfo nf_ip_afinfo = {
194 .family = AF_INET, 216 .family = AF_INET,
195 .checksum = nf_ip_checksum, 217 .checksum = nf_ip_checksum,
196 .route = nf_ip_route, 218 .checksum_partial = nf_ip_checksum_partial,
197 .saveroute = nf_ip_saveroute, 219 .route = nf_ip_route,
198 .reroute = nf_ip_reroute, 220 .saveroute = nf_ip_saveroute,
199 .route_key_size = sizeof(struct ip_rt_info), 221 .reroute = nf_ip_reroute,
222 .route_key_size = sizeof(struct ip_rt_info),
200}; 223};
201 224
202static int ipv4_netfilter_init(void) 225static int ipv4_netfilter_init(void)