diff options
-rw-r--r-- | include/linux/netfilter.h | 26 | ||||
-rw-r--r-- | include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h | 4 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_core.c | 6 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_helper.c | 30 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_proto_gre.c | 8 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_proto_icmp.c | 6 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_proto_tcp.c | 5 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_proto_udp.c | 7 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_ECN.c | 11 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_TCPMSS.c | 24 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_TOS.c | 5 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_TTL.c | 5 | ||||
-rw-r--r-- | net/netfilter/core.c | 27 |
13 files changed, 70 insertions, 94 deletions
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 707bb2e53c4e..6ab5e2d6133e 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h | |||
@@ -282,11 +282,27 @@ extern void nf_invalidate_cache(int pf); | |||
282 | Returns true or false. */ | 282 | Returns true or false. */ |
283 | extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len); | 283 | extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len); |
284 | 284 | ||
285 | extern u_int16_t nf_csum_update(u_int32_t oldval, u_int32_t newval, | 285 | static inline void nf_csum_replace4(__sum16 *sum, __be32 from, __be32 to) |
286 | u_int32_t csum); | 286 | { |
287 | extern u_int16_t nf_proto_csum_update(struct sk_buff *skb, | 287 | __be32 diff[] = { ~from, to }; |
288 | u_int32_t oldval, u_int32_t newval, | 288 | |
289 | u_int16_t csum, int pseudohdr); | 289 | *sum = csum_fold(csum_partial((char *)diff, sizeof(diff), ~csum_unfold(*sum))); |
290 | } | ||
291 | |||
292 | static inline void nf_csum_replace2(__sum16 *sum, __be16 from, __be16 to) | ||
293 | { | ||
294 | nf_csum_replace4(sum, (__force __be32)from, (__force __be32)to); | ||
295 | } | ||
296 | |||
297 | extern void nf_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb, | ||
298 | __be32 from, __be32 to, int pseudohdr); | ||
299 | |||
300 | static inline void nf_proto_csum_replace2(__sum16 *sum, struct sk_buff *skb, | ||
301 | __be16 from, __be16 to, int pseudohdr) | ||
302 | { | ||
303 | nf_proto_csum_replace4(sum, skb, (__force __be32)from, | ||
304 | (__force __be32)to, pseudohdr); | ||
305 | } | ||
290 | 306 | ||
291 | struct nf_afinfo { | 307 | struct nf_afinfo { |
292 | unsigned short family; | 308 | unsigned short family; |
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h b/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h index 1d853aa873eb..e371e0fc1672 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h | |||
@@ -102,11 +102,11 @@ static inline __be32 *gre_key(struct gre_hdr *greh) | |||
102 | } | 102 | } |
103 | 103 | ||
104 | /* get pointer ot gre csum, if present */ | 104 | /* get pointer ot gre csum, if present */ |
105 | static inline u_int16_t *gre_csum(struct gre_hdr *greh) | 105 | static inline __sum16 *gre_csum(struct gre_hdr *greh) |
106 | { | 106 | { |
107 | if (!greh->csum) | 107 | if (!greh->csum) |
108 | return NULL; | 108 | return NULL; |
109 | return (u_int16_t *) (greh+sizeof(*greh)); | 109 | return (__sum16 *) (greh+sizeof(*greh)); |
110 | } | 110 | } |
111 | 111 | ||
112 | #endif /* __KERNEL__ */ | 112 | #endif /* __KERNEL__ */ |
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index 4b6260a97408..9d1a5175dcd4 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c | |||
@@ -362,12 +362,10 @@ manip_pkt(u_int16_t proto, | |||
362 | iph = (void *)(*pskb)->data + iphdroff; | 362 | iph = (void *)(*pskb)->data + iphdroff; |
363 | 363 | ||
364 | if (maniptype == IP_NAT_MANIP_SRC) { | 364 | if (maniptype == IP_NAT_MANIP_SRC) { |
365 | iph->check = nf_csum_update(~iph->saddr, target->src.ip, | 365 | nf_csum_replace4(&iph->check, iph->saddr, target->src.ip); |
366 | iph->check); | ||
367 | iph->saddr = target->src.ip; | 366 | iph->saddr = target->src.ip; |
368 | } else { | 367 | } else { |
369 | iph->check = nf_csum_update(~iph->daddr, target->dst.ip, | 368 | nf_csum_replace4(&iph->check, iph->daddr, target->dst.ip); |
370 | iph->check); | ||
371 | iph->daddr = target->dst.ip; | 369 | iph->daddr = target->dst.ip; |
372 | } | 370 | } |
373 | return 1; | 371 | return 1; |
diff --git a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c index 3e7fd64c2162..ee80feb4b2a9 100644 --- a/net/ipv4/netfilter/ip_nat_helper.c +++ b/net/ipv4/netfilter/ip_nat_helper.c | |||
@@ -188,10 +188,8 @@ ip_nat_mangle_tcp_packet(struct sk_buff **pskb, | |||
188 | csum_partial((char *)tcph, | 188 | csum_partial((char *)tcph, |
189 | datalen, 0)); | 189 | datalen, 0)); |
190 | } else | 190 | } else |
191 | tcph->check = nf_proto_csum_update(*pskb, | 191 | nf_proto_csum_replace2(&tcph->check, *pskb, |
192 | htons(oldlen) ^ htons(0xFFFF), | 192 | htons(oldlen), htons(datalen), 1); |
193 | htons(datalen), | ||
194 | tcph->check, 1); | ||
195 | 193 | ||
196 | if (rep_len != match_len) { | 194 | if (rep_len != match_len) { |
197 | set_bit(IPS_SEQ_ADJUST_BIT, &ct->status); | 195 | set_bit(IPS_SEQ_ADJUST_BIT, &ct->status); |
@@ -266,10 +264,8 @@ ip_nat_mangle_udp_packet(struct sk_buff **pskb, | |||
266 | if (!udph->check) | 264 | if (!udph->check) |
267 | udph->check = CSUM_MANGLED_0; | 265 | udph->check = CSUM_MANGLED_0; |
268 | } else | 266 | } else |
269 | udph->check = nf_proto_csum_update(*pskb, | 267 | nf_proto_csum_replace2(&udph->check, *pskb, |
270 | htons(oldlen) ^ htons(0xFFFF), | 268 | htons(oldlen), htons(datalen), 1); |
271 | htons(datalen), | ||
272 | udph->check, 1); | ||
273 | return 1; | 269 | return 1; |
274 | } | 270 | } |
275 | EXPORT_SYMBOL(ip_nat_mangle_udp_packet); | 271 | EXPORT_SYMBOL(ip_nat_mangle_udp_packet); |
@@ -307,14 +303,10 @@ sack_adjust(struct sk_buff *skb, | |||
307 | ntohl(sack->start_seq), new_start_seq, | 303 | ntohl(sack->start_seq), new_start_seq, |
308 | ntohl(sack->end_seq), new_end_seq); | 304 | ntohl(sack->end_seq), new_end_seq); |
309 | 305 | ||
310 | tcph->check = nf_proto_csum_update(skb, | 306 | nf_proto_csum_replace4(&tcph->check, skb, |
311 | ~sack->start_seq, | 307 | sack->start_seq, new_start_seq, 0); |
312 | new_start_seq, | 308 | nf_proto_csum_replace4(&tcph->check, skb, |
313 | tcph->check, 0); | 309 | sack->end_seq, new_end_seq, 0); |
314 | tcph->check = nf_proto_csum_update(skb, | ||
315 | ~sack->end_seq, | ||
316 | new_end_seq, | ||
317 | tcph->check, 0); | ||
318 | sack->start_seq = new_start_seq; | 310 | sack->start_seq = new_start_seq; |
319 | sack->end_seq = new_end_seq; | 311 | sack->end_seq = new_end_seq; |
320 | sackoff += sizeof(*sack); | 312 | sackoff += sizeof(*sack); |
@@ -397,10 +389,8 @@ ip_nat_seq_adjust(struct sk_buff **pskb, | |||
397 | else | 389 | else |
398 | newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before); | 390 | newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before); |
399 | 391 | ||
400 | tcph->check = nf_proto_csum_update(*pskb, ~tcph->seq, newseq, | 392 | nf_proto_csum_replace4(&tcph->check, *pskb, tcph->seq, newseq, 0); |
401 | tcph->check, 0); | 393 | nf_proto_csum_replace4(&tcph->check, *pskb, tcph->ack_seq, newack, 0); |
402 | tcph->check = nf_proto_csum_update(*pskb, ~tcph->ack_seq, newack, | ||
403 | tcph->check, 0); | ||
404 | 394 | ||
405 | DEBUGP("Adjusting sequence number from %u->%u, ack from %u->%u\n", | 395 | DEBUGP("Adjusting sequence number from %u->%u, ack from %u->%u\n", |
406 | ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq), | 396 | ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq), |
diff --git a/net/ipv4/netfilter/ip_nat_proto_gre.c b/net/ipv4/netfilter/ip_nat_proto_gre.c index bf91f9312b3c..95810202d849 100644 --- a/net/ipv4/netfilter/ip_nat_proto_gre.c +++ b/net/ipv4/netfilter/ip_nat_proto_gre.c | |||
@@ -129,11 +129,9 @@ gre_manip_pkt(struct sk_buff **pskb, | |||
129 | } | 129 | } |
130 | if (greh->csum) { | 130 | if (greh->csum) { |
131 | /* FIXME: Never tested this code... */ | 131 | /* FIXME: Never tested this code... */ |
132 | *(gre_csum(greh)) = | 132 | nf_proto_csum_replace4(gre_csum(greh), *pskb, |
133 | nf_proto_csum_update(*pskb, | 133 | *(gre_key(greh)), |
134 | ~*(gre_key(greh)), | 134 | tuple->dst.u.gre.key, 0); |
135 | tuple->dst.u.gre.key, | ||
136 | *(gre_csum(greh)), 0); | ||
137 | } | 135 | } |
138 | *(gre_key(greh)) = tuple->dst.u.gre.key; | 136 | *(gre_key(greh)) = tuple->dst.u.gre.key; |
139 | break; | 137 | break; |
diff --git a/net/ipv4/netfilter/ip_nat_proto_icmp.c b/net/ipv4/netfilter/ip_nat_proto_icmp.c index 3f6efc13ac74..75266fe3e0fa 100644 --- a/net/ipv4/netfilter/ip_nat_proto_icmp.c +++ b/net/ipv4/netfilter/ip_nat_proto_icmp.c | |||
@@ -66,10 +66,8 @@ icmp_manip_pkt(struct sk_buff **pskb, | |||
66 | return 0; | 66 | return 0; |
67 | 67 | ||
68 | hdr = (struct icmphdr *)((*pskb)->data + hdroff); | 68 | hdr = (struct icmphdr *)((*pskb)->data + hdroff); |
69 | hdr->checksum = nf_proto_csum_update(*pskb, | 69 | nf_proto_csum_replace2(&hdr->checksum, *pskb, |
70 | hdr->un.echo.id ^ htons(0xFFFF), | 70 | hdr->un.echo.id, tuple->src.u.icmp.id, 0); |
71 | tuple->src.u.icmp.id, | ||
72 | hdr->checksum, 0); | ||
73 | hdr->un.echo.id = tuple->src.u.icmp.id; | 71 | hdr->un.echo.id = tuple->src.u.icmp.id; |
74 | return 1; | 72 | return 1; |
75 | } | 73 | } |
diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c index 12deb13b93b1..b586d18b3fb3 100644 --- a/net/ipv4/netfilter/ip_nat_proto_tcp.c +++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c | |||
@@ -129,9 +129,8 @@ tcp_manip_pkt(struct sk_buff **pskb, | |||
129 | if (hdrsize < sizeof(*hdr)) | 129 | if (hdrsize < sizeof(*hdr)) |
130 | return 1; | 130 | return 1; |
131 | 131 | ||
132 | hdr->check = nf_proto_csum_update(*pskb, ~oldip, newip, hdr->check, 1); | 132 | nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1); |
133 | hdr->check = nf_proto_csum_update(*pskb, oldport ^ htons(0xFFFF), newport, | 133 | nf_proto_csum_replace2(&hdr->check, *pskb, oldport, newport, 0); |
134 | hdr->check, 0); | ||
135 | return 1; | 134 | return 1; |
136 | } | 135 | } |
137 | 136 | ||
diff --git a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c index 82f8a6ab07ec..5ced0877b32f 100644 --- a/net/ipv4/netfilter/ip_nat_proto_udp.c +++ b/net/ipv4/netfilter/ip_nat_proto_udp.c | |||
@@ -115,11 +115,8 @@ udp_manip_pkt(struct sk_buff **pskb, | |||
115 | } | 115 | } |
116 | 116 | ||
117 | if (hdr->check || (*pskb)->ip_summed == CHECKSUM_PARTIAL) { | 117 | if (hdr->check || (*pskb)->ip_summed == CHECKSUM_PARTIAL) { |
118 | hdr->check = nf_proto_csum_update(*pskb, ~oldip, newip, | 118 | nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1); |
119 | hdr->check, 1); | 119 | nf_proto_csum_replace2(&hdr->check, *pskb, *portptr, newport, 0); |
120 | hdr->check = nf_proto_csum_update(*pskb, | ||
121 | *portptr ^ htons(0xFFFF), newport, | ||
122 | hdr->check, 0); | ||
123 | if (!hdr->check) | 120 | if (!hdr->check) |
124 | hdr->check = CSUM_MANGLED_0; | 121 | hdr->check = CSUM_MANGLED_0; |
125 | } | 122 | } |
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c index 1aa4517fbcdb..b55d670a24df 100644 --- a/net/ipv4/netfilter/ipt_ECN.c +++ b/net/ipv4/netfilter/ipt_ECN.c | |||
@@ -28,17 +28,16 @@ static inline int | |||
28 | set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) | 28 | set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) |
29 | { | 29 | { |
30 | struct iphdr *iph = (*pskb)->nh.iph; | 30 | struct iphdr *iph = (*pskb)->nh.iph; |
31 | u_int16_t oldtos; | ||
32 | 31 | ||
33 | if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) { | 32 | if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) { |
33 | __u8 oldtos; | ||
34 | if (!skb_make_writable(pskb, sizeof(struct iphdr))) | 34 | if (!skb_make_writable(pskb, sizeof(struct iphdr))) |
35 | return 0; | 35 | return 0; |
36 | iph = (*pskb)->nh.iph; | 36 | iph = (*pskb)->nh.iph; |
37 | oldtos = iph->tos; | 37 | oldtos = iph->tos; |
38 | iph->tos &= ~IPT_ECN_IP_MASK; | 38 | iph->tos &= ~IPT_ECN_IP_MASK; |
39 | iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK); | 39 | iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK); |
40 | iph->check = nf_csum_update(htons(oldtos) ^ htons(0xFFFF), | 40 | nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos)); |
41 | htons(iph->tos), iph->check); | ||
42 | } | 41 | } |
43 | return 1; | 42 | return 1; |
44 | } | 43 | } |
@@ -72,10 +71,8 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) | |||
72 | if (einfo->operation & IPT_ECN_OP_SET_CWR) | 71 | if (einfo->operation & IPT_ECN_OP_SET_CWR) |
73 | tcph->cwr = einfo->proto.tcp.cwr; | 72 | tcph->cwr = einfo->proto.tcp.cwr; |
74 | 73 | ||
75 | tcph->check = nf_proto_csum_update((*pskb), | 74 | nf_proto_csum_replace2(&tcph->check, *pskb, |
76 | oldval ^ htons(0xFFFF), | 75 | oldval, ((__be16 *)tcph)[6], 0); |
77 | ((__be16 *)tcph)[6], | ||
78 | tcph->check, 0); | ||
79 | return 1; | 76 | return 1; |
80 | } | 77 | } |
81 | 78 | ||
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c index 108b6b76311f..93eb5c3c1884 100644 --- a/net/ipv4/netfilter/ipt_TCPMSS.c +++ b/net/ipv4/netfilter/ipt_TCPMSS.c | |||
@@ -97,10 +97,8 @@ ipt_tcpmss_target(struct sk_buff **pskb, | |||
97 | opt[i+2] = (newmss & 0xff00) >> 8; | 97 | opt[i+2] = (newmss & 0xff00) >> 8; |
98 | opt[i+3] = (newmss & 0x00ff); | 98 | opt[i+3] = (newmss & 0x00ff); |
99 | 99 | ||
100 | tcph->check = nf_proto_csum_update(*pskb, | 100 | nf_proto_csum_replace2(&tcph->check, *pskb, |
101 | htons(oldmss)^htons(0xFFFF), | 101 | htons(oldmss), htons(newmss), 0); |
102 | htons(newmss), | ||
103 | tcph->check, 0); | ||
104 | return IPT_CONTINUE; | 102 | return IPT_CONTINUE; |
105 | } | 103 | } |
106 | } | 104 | } |
@@ -126,28 +124,22 @@ ipt_tcpmss_target(struct sk_buff **pskb, | |||
126 | opt = (u_int8_t *)tcph + sizeof(struct tcphdr); | 124 | opt = (u_int8_t *)tcph + sizeof(struct tcphdr); |
127 | memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr)); | 125 | memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr)); |
128 | 126 | ||
129 | tcph->check = nf_proto_csum_update(*pskb, | 127 | nf_proto_csum_replace2(&tcph->check, *pskb, |
130 | htons(tcplen) ^ htons(0xFFFF), | 128 | htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1); |
131 | htons(tcplen + TCPOLEN_MSS), | ||
132 | tcph->check, 1); | ||
133 | opt[0] = TCPOPT_MSS; | 129 | opt[0] = TCPOPT_MSS; |
134 | opt[1] = TCPOLEN_MSS; | 130 | opt[1] = TCPOLEN_MSS; |
135 | opt[2] = (newmss & 0xff00) >> 8; | 131 | opt[2] = (newmss & 0xff00) >> 8; |
136 | opt[3] = (newmss & 0x00ff); | 132 | opt[3] = (newmss & 0x00ff); |
137 | 133 | ||
138 | tcph->check = nf_proto_csum_update(*pskb, htonl(~0), *((__be32 *)opt), | 134 | nf_proto_csum_replace4(&tcph->check, *pskb, 0, *((__be32 *)opt), 0); |
139 | tcph->check, 0); | ||
140 | 135 | ||
141 | oldval = ((__be16 *)tcph)[6]; | 136 | oldval = ((__be16 *)tcph)[6]; |
142 | tcph->doff += TCPOLEN_MSS/4; | 137 | tcph->doff += TCPOLEN_MSS/4; |
143 | tcph->check = nf_proto_csum_update(*pskb, | 138 | nf_proto_csum_replace2(&tcph->check, *pskb, |
144 | oldval ^ htons(0xFFFF), | 139 | oldval, ((__be16 *)tcph)[6], 0); |
145 | ((__be16 *)tcph)[6], | ||
146 | tcph->check, 0); | ||
147 | 140 | ||
148 | newtotlen = htons(ntohs(iph->tot_len) + TCPOLEN_MSS); | 141 | newtotlen = htons(ntohs(iph->tot_len) + TCPOLEN_MSS); |
149 | iph->check = nf_csum_update(iph->tot_len ^ htons(0xFFFF), | 142 | nf_csum_replace2(&iph->check, iph->tot_len, newtotlen); |
150 | newtotlen, iph->check); | ||
151 | iph->tot_len = newtotlen; | 143 | iph->tot_len = newtotlen; |
152 | return IPT_CONTINUE; | 144 | return IPT_CONTINUE; |
153 | } | 145 | } |
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c index 83b80b3a5d2f..18e74ac4d425 100644 --- a/net/ipv4/netfilter/ipt_TOS.c +++ b/net/ipv4/netfilter/ipt_TOS.c | |||
@@ -30,16 +30,15 @@ target(struct sk_buff **pskb, | |||
30 | { | 30 | { |
31 | const struct ipt_tos_target_info *tosinfo = targinfo; | 31 | const struct ipt_tos_target_info *tosinfo = targinfo; |
32 | struct iphdr *iph = (*pskb)->nh.iph; | 32 | struct iphdr *iph = (*pskb)->nh.iph; |
33 | u_int16_t oldtos; | ||
34 | 33 | ||
35 | if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) { | 34 | if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) { |
35 | __u8 oldtos; | ||
36 | if (!skb_make_writable(pskb, sizeof(struct iphdr))) | 36 | if (!skb_make_writable(pskb, sizeof(struct iphdr))) |
37 | return NF_DROP; | 37 | return NF_DROP; |
38 | iph = (*pskb)->nh.iph; | 38 | iph = (*pskb)->nh.iph; |
39 | oldtos = iph->tos; | 39 | oldtos = iph->tos; |
40 | iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos; | 40 | iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos; |
41 | iph->check = nf_csum_update(htons(oldtos) ^ htons(0xFFFF), | 41 | nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos)); |
42 | htons(iph->tos), iph->check); | ||
43 | } | 42 | } |
44 | return IPT_CONTINUE; | 43 | return IPT_CONTINUE; |
45 | } | 44 | } |
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c index ac9517d62af0..fffe5ca82e91 100644 --- a/net/ipv4/netfilter/ipt_TTL.c +++ b/net/ipv4/netfilter/ipt_TTL.c | |||
@@ -54,9 +54,8 @@ ipt_ttl_target(struct sk_buff **pskb, | |||
54 | } | 54 | } |
55 | 55 | ||
56 | if (new_ttl != iph->ttl) { | 56 | if (new_ttl != iph->ttl) { |
57 | iph->check = nf_csum_update(htons((iph->ttl << 8)) ^ htons(0xFFFF), | 57 | nf_csum_replace2(&iph->check, htons(iph->ttl << 8), |
58 | htons(new_ttl << 8), | 58 | htons(new_ttl << 8)); |
59 | iph->check); | ||
60 | iph->ttl = new_ttl; | 59 | iph->ttl = new_ttl; |
61 | } | 60 | } |
62 | 61 | ||
diff --git a/net/netfilter/core.c b/net/netfilter/core.c index d80b935b3a92..17f9e1cbc73b 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c | |||
@@ -222,28 +222,21 @@ copy_skb: | |||
222 | } | 222 | } |
223 | EXPORT_SYMBOL(skb_make_writable); | 223 | EXPORT_SYMBOL(skb_make_writable); |
224 | 224 | ||
225 | u_int16_t nf_csum_update(u_int32_t oldval, u_int32_t newval, u_int32_t csum) | 225 | void nf_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb, |
226 | { | 226 | __be32 from, __be32 to, int pseudohdr) |
227 | u_int32_t diff[] = { oldval, newval }; | ||
228 | |||
229 | return csum_fold(csum_partial((char *)diff, sizeof(diff), ~csum)); | ||
230 | } | ||
231 | EXPORT_SYMBOL(nf_csum_update); | ||
232 | |||
233 | u_int16_t nf_proto_csum_update(struct sk_buff *skb, | ||
234 | u_int32_t oldval, u_int32_t newval, | ||
235 | u_int16_t csum, int pseudohdr) | ||
236 | { | 227 | { |
228 | __be32 diff[] = { ~from, to }; | ||
237 | if (skb->ip_summed != CHECKSUM_PARTIAL) { | 229 | if (skb->ip_summed != CHECKSUM_PARTIAL) { |
238 | csum = nf_csum_update(oldval, newval, csum); | 230 | *sum = csum_fold(csum_partial((char *)diff, sizeof(diff), |
231 | ~csum_unfold(*sum))); | ||
239 | if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr) | 232 | if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr) |
240 | skb->csum = nf_csum_update(oldval, newval, skb->csum); | 233 | skb->csum = ~csum_partial((char *)diff, sizeof(diff), |
234 | ~skb->csum); | ||
241 | } else if (pseudohdr) | 235 | } else if (pseudohdr) |
242 | csum = ~nf_csum_update(oldval, newval, ~csum); | 236 | *sum = ~csum_fold(csum_partial((char *)diff, sizeof(diff), |
243 | 237 | csum_unfold(*sum))); | |
244 | return csum; | ||
245 | } | 238 | } |
246 | EXPORT_SYMBOL(nf_proto_csum_update); | 239 | EXPORT_SYMBOL(nf_proto_csum_replace4); |
247 | 240 | ||
248 | /* This does not belong here, but locally generated errors need it if connection | 241 | /* This does not belong here, but locally generated errors need it if connection |
249 | tracking in use: without this, connection may not be in hash table, and hence | 242 | tracking in use: without this, connection may not be in hash table, and hence |