diff options
author | Patrick McHardy <kaber@trash.net> | 2008-03-20 10:15:53 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2008-04-14 05:15:49 -0400 |
commit | d63a650736f566a1f9e9434725d2089597c0d2cc (patch) | |
tree | f0a3d5dbc9ced46f95582e4133b55bb70a1ae365 /net/ipv4 | |
parent | 6185f870e293a0a3eae5c81eb0106480cf03dfde (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.c | 37 |
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 | |||
186 | EXPORT_SYMBOL(nf_ip_checksum); | 185 | EXPORT_SYMBOL(nf_ip_checksum); |
187 | 186 | ||
187 | static __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 | |||
188 | static int nf_ip_route(struct dst_entry **dst, struct flowi *fl) | 210 | static 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 | ||
193 | static const struct nf_afinfo nf_ip_afinfo = { | 215 | static 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 | ||
202 | static int ipv4_netfilter_init(void) | 225 | static int ipv4_netfilter_init(void) |