aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
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/ipv6
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/ipv6')
-rw-r--r--net/ipv6/netfilter.c42
1 files changed, 35 insertions, 7 deletions
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index aed51bcc66b4..8c6c5e71f210 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -121,16 +121,44 @@ __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
121 } 121 }
122 return csum; 122 return csum;
123} 123}
124
125EXPORT_SYMBOL(nf_ip6_checksum); 124EXPORT_SYMBOL(nf_ip6_checksum);
126 125
126static __sum16 nf_ip6_checksum_partial(struct sk_buff *skb, unsigned int hook,
127 unsigned int dataoff, unsigned int len,
128 u_int8_t protocol)
129{
130 struct ipv6hdr *ip6h = ipv6_hdr(skb);
131 __wsum hsum;
132 __sum16 csum = 0;
133
134 switch (skb->ip_summed) {
135 case CHECKSUM_COMPLETE:
136 if (len == skb->len - dataoff)
137 return nf_ip6_checksum(skb, hook, dataoff, protocol);
138 /* fall through */
139 case CHECKSUM_NONE:
140 hsum = skb_checksum(skb, 0, dataoff, 0);
141 skb->csum = ~csum_unfold(csum_ipv6_magic(&ip6h->saddr,
142 &ip6h->daddr,
143 skb->len - dataoff,
144 protocol,
145 csum_sub(0, hsum)));
146 skb->ip_summed = CHECKSUM_NONE;
147 csum = __skb_checksum_complete_head(skb, dataoff + len);
148 if (!csum)
149 skb->ip_summed = CHECKSUM_UNNECESSARY;
150 }
151 return csum;
152};
153
127static const struct nf_afinfo nf_ip6_afinfo = { 154static const struct nf_afinfo nf_ip6_afinfo = {
128 .family = AF_INET6, 155 .family = AF_INET6,
129 .checksum = nf_ip6_checksum, 156 .checksum = nf_ip6_checksum,
130 .route = nf_ip6_route, 157 .checksum_partial = nf_ip6_checksum_partial,
131 .saveroute = nf_ip6_saveroute, 158 .route = nf_ip6_route,
132 .reroute = nf_ip6_reroute, 159 .saveroute = nf_ip6_saveroute,
133 .route_key_size = sizeof(struct ip6_rt_info), 160 .reroute = nf_ip6_reroute,
161 .route_key_size = sizeof(struct ip6_rt_info),
134}; 162};
135 163
136int __init ipv6_netfilter_init(void) 164int __init ipv6_netfilter_init(void)