diff options
author | Changli Gao <xiaosuo@gmail.com> | 2010-09-15 13:24:50 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2010-09-15 13:24:50 -0400 |
commit | 0abee5260babe0a12d468b485a28336551697925 (patch) | |
tree | e7da178d0eb31ef4bd69ed6f63629d0eb7a19407 | |
parent | 068e8a30320e33b1f8d15df9eaef84f04258f96d (diff) |
netfilter: nf_nat: add nf_nat_csum()
Add a static function nf_nat_csum() to replace the duplicate code in
nf_nat_mangle_udp_packet() and __nf_nat_mangle_tcp_packet().
Signed-off-by: Changli Gao <xiaosuo@gmail.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r-- | net/ipv4/netfilter/nf_nat_helper.c | 76 |
1 files changed, 31 insertions, 45 deletions
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 4a0c6b548eee..31427fb57aa8 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c | |||
@@ -153,6 +153,35 @@ void nf_nat_set_seq_adjust(struct nf_conn *ct, enum ip_conntrack_info ctinfo, | |||
153 | } | 153 | } |
154 | EXPORT_SYMBOL_GPL(nf_nat_set_seq_adjust); | 154 | EXPORT_SYMBOL_GPL(nf_nat_set_seq_adjust); |
155 | 155 | ||
156 | static void nf_nat_csum(struct sk_buff *skb, struct iphdr *iph, void *data, | ||
157 | int datalen, __sum16 *check, int oldlen) | ||
158 | { | ||
159 | struct rtable *rt = skb_rtable(skb); | ||
160 | |||
161 | if (skb->ip_summed != CHECKSUM_PARTIAL) { | ||
162 | if (!(rt->rt_flags & RTCF_LOCAL) && | ||
163 | skb->dev->features & NETIF_F_V4_CSUM) { | ||
164 | skb->ip_summed = CHECKSUM_PARTIAL; | ||
165 | skb->csum_start = skb_headroom(skb) + | ||
166 | skb_network_offset(skb) + | ||
167 | iph->ihl * 4; | ||
168 | skb->csum_offset = (void *)check - data; | ||
169 | *check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, | ||
170 | datalen, iph->protocol, 0); | ||
171 | } else { | ||
172 | *check = 0; | ||
173 | *check = csum_tcpudp_magic(iph->saddr, iph->daddr, | ||
174 | datalen, iph->protocol, | ||
175 | csum_partial(data, datalen, | ||
176 | 0)); | ||
177 | if (iph->protocol == IPPROTO_UDP && !*check) | ||
178 | *check = CSUM_MANGLED_0; | ||
179 | } | ||
180 | } else | ||
181 | inet_proto_csum_replace2(check, skb, | ||
182 | htons(oldlen), htons(datalen), 1); | ||
183 | } | ||
184 | |||
156 | /* Generic function for mangling variable-length address changes inside | 185 | /* Generic function for mangling variable-length address changes inside |
157 | * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX | 186 | * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX |
158 | * command in FTP). | 187 | * command in FTP). |
@@ -169,7 +198,6 @@ int __nf_nat_mangle_tcp_packet(struct sk_buff *skb, | |||
169 | const char *rep_buffer, | 198 | const char *rep_buffer, |
170 | unsigned int rep_len, bool adjust) | 199 | unsigned int rep_len, bool adjust) |
171 | { | 200 | { |
172 | struct rtable *rt = skb_rtable(skb); | ||
173 | struct iphdr *iph; | 201 | struct iphdr *iph; |
174 | struct tcphdr *tcph; | 202 | struct tcphdr *tcph; |
175 | int oldlen, datalen; | 203 | int oldlen, datalen; |
@@ -192,26 +220,7 @@ int __nf_nat_mangle_tcp_packet(struct sk_buff *skb, | |||
192 | match_offset, match_len, rep_buffer, rep_len); | 220 | match_offset, match_len, rep_buffer, rep_len); |
193 | 221 | ||
194 | datalen = skb->len - iph->ihl*4; | 222 | datalen = skb->len - iph->ihl*4; |
195 | if (skb->ip_summed != CHECKSUM_PARTIAL) { | 223 | nf_nat_csum(skb, iph, tcph, datalen, &tcph->check, oldlen); |
196 | if (!(rt->rt_flags & RTCF_LOCAL) && | ||
197 | skb->dev->features & NETIF_F_V4_CSUM) { | ||
198 | skb->ip_summed = CHECKSUM_PARTIAL; | ||
199 | skb->csum_start = skb_headroom(skb) + | ||
200 | skb_network_offset(skb) + | ||
201 | iph->ihl * 4; | ||
202 | skb->csum_offset = offsetof(struct tcphdr, check); | ||
203 | tcph->check = ~tcp_v4_check(datalen, | ||
204 | iph->saddr, iph->daddr, 0); | ||
205 | } else { | ||
206 | tcph->check = 0; | ||
207 | tcph->check = tcp_v4_check(datalen, | ||
208 | iph->saddr, iph->daddr, | ||
209 | csum_partial(tcph, | ||
210 | datalen, 0)); | ||
211 | } | ||
212 | } else | ||
213 | inet_proto_csum_replace2(&tcph->check, skb, | ||
214 | htons(oldlen), htons(datalen), 1); | ||
215 | 224 | ||
216 | if (adjust && rep_len != match_len) | 225 | if (adjust && rep_len != match_len) |
217 | nf_nat_set_seq_adjust(ct, ctinfo, tcph->seq, | 226 | nf_nat_set_seq_adjust(ct, ctinfo, tcph->seq, |
@@ -240,7 +249,6 @@ nf_nat_mangle_udp_packet(struct sk_buff *skb, | |||
240 | const char *rep_buffer, | 249 | const char *rep_buffer, |
241 | unsigned int rep_len) | 250 | unsigned int rep_len) |
242 | { | 251 | { |
243 | struct rtable *rt = skb_rtable(skb); | ||
244 | struct iphdr *iph; | 252 | struct iphdr *iph; |
245 | struct udphdr *udph; | 253 | struct udphdr *udph; |
246 | int datalen, oldlen; | 254 | int datalen, oldlen; |
@@ -274,29 +282,7 @@ nf_nat_mangle_udp_packet(struct sk_buff *skb, | |||
274 | if (!udph->check && skb->ip_summed != CHECKSUM_PARTIAL) | 282 | if (!udph->check && skb->ip_summed != CHECKSUM_PARTIAL) |
275 | return 1; | 283 | return 1; |
276 | 284 | ||
277 | if (skb->ip_summed != CHECKSUM_PARTIAL) { | 285 | nf_nat_csum(skb, iph, udph, datalen, &udph->check, oldlen); |
278 | if (!(rt->rt_flags & RTCF_LOCAL) && | ||
279 | skb->dev->features & NETIF_F_V4_CSUM) { | ||
280 | skb->ip_summed = CHECKSUM_PARTIAL; | ||
281 | skb->csum_start = skb_headroom(skb) + | ||
282 | skb_network_offset(skb) + | ||
283 | iph->ihl * 4; | ||
284 | skb->csum_offset = offsetof(struct udphdr, check); | ||
285 | udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, | ||
286 | datalen, IPPROTO_UDP, | ||
287 | 0); | ||
288 | } else { | ||
289 | udph->check = 0; | ||
290 | udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, | ||
291 | datalen, IPPROTO_UDP, | ||
292 | csum_partial(udph, | ||
293 | datalen, 0)); | ||
294 | if (!udph->check) | ||
295 | udph->check = CSUM_MANGLED_0; | ||
296 | } | ||
297 | } else | ||
298 | inet_proto_csum_replace2(&udph->check, skb, | ||
299 | htons(oldlen), htons(datalen), 1); | ||
300 | 286 | ||
301 | return 1; | 287 | return 1; |
302 | } | 288 | } |