diff options
Diffstat (limited to 'net/ipv4')
30 files changed, 226 insertions, 199 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 95b9d81ac4..3ffa60dadc 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -1135,7 +1135,7 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa) | |||
1135 | 1135 | ||
1136 | if (!skb) | 1136 | if (!skb) |
1137 | netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, ENOBUFS); | 1137 | netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, ENOBUFS); |
1138 | else if (inet_fill_ifaddr(skb, ifa, current->pid, 0, event, 0) < 0) { | 1138 | else if (inet_fill_ifaddr(skb, ifa, 0, 0, event, 0) < 0) { |
1139 | kfree_skb(skb); | 1139 | kfree_skb(skb); |
1140 | netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, EINVAL); | 1140 | netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, EINVAL); |
1141 | } else { | 1141 | } else { |
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 73bfcae8af..09590f3560 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c | |||
@@ -12,13 +12,6 @@ | |||
12 | #include <net/protocol.h> | 12 | #include <net/protocol.h> |
13 | #include <net/udp.h> | 13 | #include <net/udp.h> |
14 | 14 | ||
15 | /* decapsulation data for use when post-processing */ | ||
16 | struct esp_decap_data { | ||
17 | xfrm_address_t saddr; | ||
18 | __u16 sport; | ||
19 | __u8 proto; | ||
20 | }; | ||
21 | |||
22 | static int esp_output(struct xfrm_state *x, struct sk_buff *skb) | 15 | static int esp_output(struct xfrm_state *x, struct sk_buff *skb) |
23 | { | 16 | { |
24 | int err; | 17 | int err; |
@@ -150,6 +143,10 @@ static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc | |||
150 | int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen; | 143 | int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen; |
151 | int nfrags; | 144 | int nfrags; |
152 | int encap_len = 0; | 145 | int encap_len = 0; |
146 | u8 nexthdr[2]; | ||
147 | struct scatterlist *sg; | ||
148 | u8 workbuf[60]; | ||
149 | int padlen; | ||
153 | 150 | ||
154 | if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr))) | 151 | if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr))) |
155 | goto out; | 152 | goto out; |
@@ -185,122 +182,82 @@ static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc | |||
185 | if (esp->conf.ivlen) | 182 | if (esp->conf.ivlen) |
186 | crypto_cipher_set_iv(esp->conf.tfm, esph->enc_data, crypto_tfm_alg_ivsize(esp->conf.tfm)); | 183 | crypto_cipher_set_iv(esp->conf.tfm, esph->enc_data, crypto_tfm_alg_ivsize(esp->conf.tfm)); |
187 | 184 | ||
188 | { | 185 | sg = &esp->sgbuf[0]; |
189 | u8 nexthdr[2]; | ||
190 | struct scatterlist *sg = &esp->sgbuf[0]; | ||
191 | u8 workbuf[60]; | ||
192 | int padlen; | ||
193 | |||
194 | if (unlikely(nfrags > ESP_NUM_FAST_SG)) { | ||
195 | sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); | ||
196 | if (!sg) | ||
197 | goto out; | ||
198 | } | ||
199 | skb_to_sgvec(skb, sg, sizeof(struct ip_esp_hdr) + esp->conf.ivlen, elen); | ||
200 | crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen); | ||
201 | if (unlikely(sg != &esp->sgbuf[0])) | ||
202 | kfree(sg); | ||
203 | |||
204 | if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) | ||
205 | BUG(); | ||
206 | 186 | ||
207 | padlen = nexthdr[0]; | 187 | if (unlikely(nfrags > ESP_NUM_FAST_SG)) { |
208 | if (padlen+2 >= elen) | 188 | sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); |
189 | if (!sg) | ||
209 | goto out; | 190 | goto out; |
210 | |||
211 | /* ... check padding bits here. Silly. :-) */ | ||
212 | |||
213 | if (x->encap && decap && decap->decap_type) { | ||
214 | struct esp_decap_data *encap_data; | ||
215 | struct udphdr *uh = (struct udphdr *) (iph+1); | ||
216 | |||
217 | encap_data = (struct esp_decap_data *) (decap->decap_data); | ||
218 | encap_data->proto = 0; | ||
219 | |||
220 | switch (decap->decap_type) { | ||
221 | case UDP_ENCAP_ESPINUDP: | ||
222 | case UDP_ENCAP_ESPINUDP_NON_IKE: | ||
223 | encap_data->proto = AF_INET; | ||
224 | encap_data->saddr.a4 = iph->saddr; | ||
225 | encap_data->sport = uh->source; | ||
226 | encap_len = (void*)esph - (void*)uh; | ||
227 | break; | ||
228 | |||
229 | default: | ||
230 | goto out; | ||
231 | } | ||
232 | } | ||
233 | |||
234 | iph->protocol = nexthdr[1]; | ||
235 | pskb_trim(skb, skb->len - alen - padlen - 2); | ||
236 | memcpy(workbuf, skb->nh.raw, iph->ihl*4); | ||
237 | skb->h.raw = skb_pull(skb, sizeof(struct ip_esp_hdr) + esp->conf.ivlen); | ||
238 | skb->nh.raw += encap_len + sizeof(struct ip_esp_hdr) + esp->conf.ivlen; | ||
239 | memcpy(skb->nh.raw, workbuf, iph->ihl*4); | ||
240 | skb->nh.iph->tot_len = htons(skb->len); | ||
241 | } | 191 | } |
192 | skb_to_sgvec(skb, sg, sizeof(struct ip_esp_hdr) + esp->conf.ivlen, elen); | ||
193 | crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen); | ||
194 | if (unlikely(sg != &esp->sgbuf[0])) | ||
195 | kfree(sg); | ||
242 | 196 | ||
243 | return 0; | 197 | if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) |
198 | BUG(); | ||
244 | 199 | ||
245 | out: | 200 | padlen = nexthdr[0]; |
246 | return -EINVAL; | 201 | if (padlen+2 >= elen) |
247 | } | 202 | goto out; |
248 | 203 | ||
249 | static int esp_post_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) | 204 | /* ... check padding bits here. Silly. :-) */ |
250 | { | ||
251 | |||
252 | if (x->encap) { | ||
253 | struct xfrm_encap_tmpl *encap; | ||
254 | struct esp_decap_data *decap_data; | ||
255 | 205 | ||
256 | encap = x->encap; | 206 | if (x->encap) { |
257 | decap_data = (struct esp_decap_data *)(decap->decap_data); | 207 | struct xfrm_encap_tmpl *encap = x->encap; |
208 | struct udphdr *uh; | ||
258 | 209 | ||
259 | /* first, make sure that the decap type == the encap type */ | ||
260 | if (encap->encap_type != decap->decap_type) | 210 | if (encap->encap_type != decap->decap_type) |
261 | return -EINVAL; | 211 | goto out; |
262 | 212 | ||
263 | switch (encap->encap_type) { | 213 | uh = (struct udphdr *)(iph + 1); |
264 | default: | 214 | encap_len = (void*)esph - (void*)uh; |
265 | case UDP_ENCAP_ESPINUDP: | 215 | |
266 | case UDP_ENCAP_ESPINUDP_NON_IKE: | 216 | /* |
267 | /* | 217 | * 1) if the NAT-T peer's IP or port changed then |
268 | * 1) if the NAT-T peer's IP or port changed then | 218 | * advertize the change to the keying daemon. |
269 | * advertize the change to the keying daemon. | 219 | * This is an inbound SA, so just compare |
270 | * This is an inbound SA, so just compare | 220 | * SRC ports. |
271 | * SRC ports. | 221 | */ |
272 | */ | 222 | if (iph->saddr != x->props.saddr.a4 || |
273 | if (decap_data->proto == AF_INET && | 223 | uh->source != encap->encap_sport) { |
274 | (decap_data->saddr.a4 != x->props.saddr.a4 || | 224 | xfrm_address_t ipaddr; |
275 | decap_data->sport != encap->encap_sport)) { | 225 | |
276 | xfrm_address_t ipaddr; | 226 | ipaddr.a4 = iph->saddr; |
277 | 227 | km_new_mapping(x, &ipaddr, uh->source); | |
278 | ipaddr.a4 = decap_data->saddr.a4; | 228 | |
279 | km_new_mapping(x, &ipaddr, decap_data->sport); | 229 | /* XXX: perhaps add an extra |
280 | 230 | * policy check here, to see | |
281 | /* XXX: perhaps add an extra | 231 | * if we should allow or |
282 | * policy check here, to see | 232 | * reject a packet from a |
283 | * if we should allow or | 233 | * different source |
284 | * reject a packet from a | 234 | * address/port. |
285 | * different source | ||
286 | * address/port. | ||
287 | */ | ||
288 | } | ||
289 | |||
290 | /* | ||
291 | * 2) ignore UDP/TCP checksums in case | ||
292 | * of NAT-T in Transport Mode, or | ||
293 | * perform other post-processing fixes | ||
294 | * as per * draft-ietf-ipsec-udp-encaps-06, | ||
295 | * section 3.1.2 | ||
296 | */ | 235 | */ |
297 | if (!x->props.mode) | ||
298 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
299 | |||
300 | break; | ||
301 | } | 236 | } |
237 | |||
238 | /* | ||
239 | * 2) ignore UDP/TCP checksums in case | ||
240 | * of NAT-T in Transport Mode, or | ||
241 | * perform other post-processing fixes | ||
242 | * as per draft-ietf-ipsec-udp-encaps-06, | ||
243 | * section 3.1.2 | ||
244 | */ | ||
245 | if (!x->props.mode) | ||
246 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
302 | } | 247 | } |
248 | |||
249 | iph->protocol = nexthdr[1]; | ||
250 | pskb_trim(skb, skb->len - alen - padlen - 2); | ||
251 | memcpy(workbuf, skb->nh.raw, iph->ihl*4); | ||
252 | skb->h.raw = skb_pull(skb, sizeof(struct ip_esp_hdr) + esp->conf.ivlen); | ||
253 | skb->nh.raw += encap_len + sizeof(struct ip_esp_hdr) + esp->conf.ivlen; | ||
254 | memcpy(skb->nh.raw, workbuf, iph->ihl*4); | ||
255 | skb->nh.iph->tot_len = htons(skb->len); | ||
256 | |||
303 | return 0; | 257 | return 0; |
258 | |||
259 | out: | ||
260 | return -EINVAL; | ||
304 | } | 261 | } |
305 | 262 | ||
306 | static u32 esp4_get_max_size(struct xfrm_state *x, int mtu) | 263 | static u32 esp4_get_max_size(struct xfrm_state *x, int mtu) |
@@ -458,7 +415,6 @@ static struct xfrm_type esp_type = | |||
458 | .destructor = esp_destroy, | 415 | .destructor = esp_destroy, |
459 | .get_max_size = esp4_get_max_size, | 416 | .get_max_size = esp4_get_max_size, |
460 | .input = esp_input, | 417 | .input = esp_input, |
461 | .post_input = esp_post_input, | ||
462 | .output = esp_output | 418 | .output = esp_output |
463 | }; | 419 | }; |
464 | 420 | ||
@@ -470,15 +426,6 @@ static struct net_protocol esp4_protocol = { | |||
470 | 426 | ||
471 | static int __init esp4_init(void) | 427 | static int __init esp4_init(void) |
472 | { | 428 | { |
473 | struct xfrm_decap_state decap; | ||
474 | |||
475 | if (sizeof(struct esp_decap_data) > | ||
476 | sizeof(decap.decap_data)) { | ||
477 | extern void decap_data_too_small(void); | ||
478 | |||
479 | decap_data_too_small(); | ||
480 | } | ||
481 | |||
482 | if (xfrm_register_type(&esp_type, AF_INET) < 0) { | 429 | if (xfrm_register_type(&esp_type, AF_INET) < 0) { |
483 | printk(KERN_INFO "ip esp init: can't add xfrm type\n"); | 430 | printk(KERN_INFO "ip esp init: can't add xfrm type\n"); |
484 | return -EAGAIN; | 431 | return -EAGAIN; |
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index ef4724de73..0f4145babb 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c | |||
@@ -1045,7 +1045,7 @@ fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm, | |||
1045 | } | 1045 | } |
1046 | 1046 | ||
1047 | nl->nlmsg_flags = NLM_F_REQUEST; | 1047 | nl->nlmsg_flags = NLM_F_REQUEST; |
1048 | nl->nlmsg_pid = current->pid; | 1048 | nl->nlmsg_pid = 0; |
1049 | nl->nlmsg_seq = 0; | 1049 | nl->nlmsg_seq = 0; |
1050 | nl->nlmsg_len = NLMSG_LENGTH(sizeof(*rtm)); | 1050 | nl->nlmsg_len = NLMSG_LENGTH(sizeof(*rtm)); |
1051 | if (cmd == SIOCDELRT) { | 1051 | if (cmd == SIOCDELRT) { |
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 105039eb76..e7bbff4340 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -192,7 +192,7 @@ int sysctl_icmp_echo_ignore_all; | |||
192 | int sysctl_icmp_echo_ignore_broadcasts = 1; | 192 | int sysctl_icmp_echo_ignore_broadcasts = 1; |
193 | 193 | ||
194 | /* Control parameter - ignore bogus broadcast responses? */ | 194 | /* Control parameter - ignore bogus broadcast responses? */ |
195 | int sysctl_icmp_ignore_bogus_error_responses; | 195 | int sysctl_icmp_ignore_bogus_error_responses = 1; |
196 | 196 | ||
197 | /* | 197 | /* |
198 | * Configurable global rate limit. | 198 | * Configurable global rate limit. |
@@ -385,7 +385,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) | |||
385 | u32 daddr; | 385 | u32 daddr; |
386 | 386 | ||
387 | if (ip_options_echo(&icmp_param->replyopts, skb)) | 387 | if (ip_options_echo(&icmp_param->replyopts, skb)) |
388 | goto out; | 388 | return; |
389 | 389 | ||
390 | if (icmp_xmit_lock()) | 390 | if (icmp_xmit_lock()) |
391 | return; | 391 | return; |
@@ -416,7 +416,6 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) | |||
416 | ip_rt_put(rt); | 416 | ip_rt_put(rt); |
417 | out_unlock: | 417 | out_unlock: |
418 | icmp_xmit_unlock(); | 418 | icmp_xmit_unlock(); |
419 | out:; | ||
420 | } | 419 | } |
421 | 420 | ||
422 | 421 | ||
@@ -525,7 +524,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info) | |||
525 | iph->tos; | 524 | iph->tos; |
526 | 525 | ||
527 | if (ip_options_echo(&icmp_param.replyopts, skb_in)) | 526 | if (ip_options_echo(&icmp_param.replyopts, skb_in)) |
528 | goto ende; | 527 | goto out_unlock; |
529 | 528 | ||
530 | 529 | ||
531 | /* | 530 | /* |
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index d8ce7133cd..64ce52bf04 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -970,7 +970,7 @@ int igmp_rcv(struct sk_buff *skb) | |||
970 | case IGMP_MTRACE_RESP: | 970 | case IGMP_MTRACE_RESP: |
971 | break; | 971 | break; |
972 | default: | 972 | default: |
973 | NETDEBUG(KERN_DEBUG "New IGMP type=%d, why we do not know about it?\n", ih->type); | 973 | break; |
974 | } | 974 | } |
975 | 975 | ||
976 | drop: | 976 | drop: |
@@ -1578,7 +1578,7 @@ static int sf_setstate(struct ip_mc_list *pmc) | |||
1578 | new_in = psf->sf_count[MCAST_INCLUDE] != 0; | 1578 | new_in = psf->sf_count[MCAST_INCLUDE] != 0; |
1579 | if (new_in) { | 1579 | if (new_in) { |
1580 | if (!psf->sf_oldin) { | 1580 | if (!psf->sf_oldin) { |
1581 | struct ip_sf_list *prev = 0; | 1581 | struct ip_sf_list *prev = NULL; |
1582 | 1582 | ||
1583 | for (dpsf=pmc->tomb; dpsf; dpsf=dpsf->sf_next) { | 1583 | for (dpsf=pmc->tomb; dpsf; dpsf=dpsf->sf_next) { |
1584 | if (dpsf->sf_inaddr == psf->sf_inaddr) | 1584 | if (dpsf->sf_inaddr == psf->sf_inaddr) |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index abe23923e4..9981dcd68f 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -830,7 +830,8 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
830 | skb->h.raw = skb->nh.raw; | 830 | skb->h.raw = skb->nh.raw; |
831 | skb->nh.raw = skb_push(skb, gre_hlen); | 831 | skb->nh.raw = skb_push(skb, gre_hlen); |
832 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 832 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
833 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE|IPSKB_XFRM_TRANSFORMED); | 833 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | |
834 | IPSKB_REROUTED); | ||
834 | dst_release(skb->dst); | 835 | dst_release(skb->dst); |
835 | skb->dst = &rt->u.dst; | 836 | skb->dst = &rt->u.dst; |
836 | 837 | ||
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 3324fbfe52..8ee4d01674 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -207,8 +207,10 @@ static inline int ip_finish_output(struct sk_buff *skb) | |||
207 | { | 207 | { |
208 | #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) | 208 | #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) |
209 | /* Policy lookup after SNAT yielded a new policy */ | 209 | /* Policy lookup after SNAT yielded a new policy */ |
210 | if (skb->dst->xfrm != NULL) | 210 | if (skb->dst->xfrm != NULL) { |
211 | return xfrm4_output_finish(skb); | 211 | IPCB(skb)->flags |= IPSKB_REROUTED; |
212 | return dst_output(skb); | ||
213 | } | ||
212 | #endif | 214 | #endif |
213 | if (skb->len > dst_mtu(skb->dst) && | 215 | if (skb->len > dst_mtu(skb->dst) && |
214 | !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size)) | 216 | !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size)) |
@@ -271,8 +273,9 @@ int ip_mc_output(struct sk_buff *skb) | |||
271 | newskb->dev, ip_dev_loopback_xmit); | 273 | newskb->dev, ip_dev_loopback_xmit); |
272 | } | 274 | } |
273 | 275 | ||
274 | return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dev, | 276 | return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dev, |
275 | ip_finish_output); | 277 | ip_finish_output, |
278 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | ||
276 | } | 279 | } |
277 | 280 | ||
278 | int ip_output(struct sk_buff *skb) | 281 | int ip_output(struct sk_buff *skb) |
@@ -284,8 +287,9 @@ int ip_output(struct sk_buff *skb) | |||
284 | skb->dev = dev; | 287 | skb->dev = dev; |
285 | skb->protocol = htons(ETH_P_IP); | 288 | skb->protocol = htons(ETH_P_IP); |
286 | 289 | ||
287 | return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev, | 290 | return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev, |
288 | ip_finish_output); | 291 | ip_finish_output, |
292 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | ||
289 | } | 293 | } |
290 | 294 | ||
291 | int ip_queue_xmit(struct sk_buff *skb, int ipfragok) | 295 | int ip_queue_xmit(struct sk_buff *skb, int ipfragok) |
@@ -843,10 +847,11 @@ int ip_append_data(struct sock *sk, | |||
843 | if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) && | 847 | if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) && |
844 | (rt->u.dst.dev->features & NETIF_F_UFO)) { | 848 | (rt->u.dst.dev->features & NETIF_F_UFO)) { |
845 | 849 | ||
846 | if(ip_ufo_append_data(sk, getfrag, from, length, hh_len, | 850 | err = ip_ufo_append_data(sk, getfrag, from, length, hh_len, |
847 | fragheaderlen, transhdrlen, mtu, flags)) | 851 | fragheaderlen, transhdrlen, mtu, |
852 | flags); | ||
853 | if (err) | ||
848 | goto error; | 854 | goto error; |
849 | |||
850 | return 0; | 855 | return 0; |
851 | } | 856 | } |
852 | 857 | ||
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index e5cbe72c6b..03d13742a4 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -622,7 +622,8 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
622 | skb->h.raw = skb->nh.raw; | 622 | skb->h.raw = skb->nh.raw; |
623 | skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); | 623 | skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); |
624 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 624 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
625 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE|IPSKB_XFRM_TRANSFORMED); | 625 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | |
626 | IPSKB_REROUTED); | ||
626 | dst_release(skb->dst); | 627 | dst_release(skb->dst); |
627 | skb->dst = &rt->u.dst; | 628 | skb->dst = &rt->u.dst; |
628 | 629 | ||
diff --git a/net/ipv4/multipath_wrandom.c b/net/ipv4/multipath_wrandom.c index d34a9fa608..342d0b9098 100644 --- a/net/ipv4/multipath_wrandom.c +++ b/net/ipv4/multipath_wrandom.c | |||
@@ -228,7 +228,7 @@ static void wrandom_set_nhinfo(__u32 network, | |||
228 | struct multipath_dest *d, *target_dest = NULL; | 228 | struct multipath_dest *d, *target_dest = NULL; |
229 | 229 | ||
230 | /* store the weight information for a certain route */ | 230 | /* store the weight information for a certain route */ |
231 | spin_lock(&state[state_idx].lock); | 231 | spin_lock_bh(&state[state_idx].lock); |
232 | 232 | ||
233 | /* find state entry for gateway or add one if necessary */ | 233 | /* find state entry for gateway or add one if necessary */ |
234 | list_for_each_entry_rcu(r, &state[state_idx].head, list) { | 234 | list_for_each_entry_rcu(r, &state[state_idx].head, list) { |
@@ -276,7 +276,7 @@ static void wrandom_set_nhinfo(__u32 network, | |||
276 | * we are finished | 276 | * we are finished |
277 | */ | 277 | */ |
278 | 278 | ||
279 | spin_unlock(&state[state_idx].lock); | 279 | spin_unlock_bh(&state[state_idx].lock); |
280 | } | 280 | } |
281 | 281 | ||
282 | static void __multipath_free(struct rcu_head *head) | 282 | static void __multipath_free(struct rcu_head *head) |
@@ -302,7 +302,7 @@ static void wrandom_flush(void) | |||
302 | for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) { | 302 | for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) { |
303 | struct multipath_route *r; | 303 | struct multipath_route *r; |
304 | 304 | ||
305 | spin_lock(&state[i].lock); | 305 | spin_lock_bh(&state[i].lock); |
306 | list_for_each_entry_rcu(r, &state[i].head, list) { | 306 | list_for_each_entry_rcu(r, &state[i].head, list) { |
307 | struct multipath_dest *d; | 307 | struct multipath_dest *d; |
308 | list_for_each_entry_rcu(d, &r->dests, list) { | 308 | list_for_each_entry_rcu(d, &r->dests, list) { |
@@ -315,7 +315,7 @@ static void wrandom_flush(void) | |||
315 | __multipath_free); | 315 | __multipath_free); |
316 | } | 316 | } |
317 | 317 | ||
318 | spin_unlock(&state[i].lock); | 318 | spin_unlock_bh(&state[i].lock); |
319 | } | 319 | } |
320 | } | 320 | } |
321 | 321 | ||
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index 52a3d7c579..ed42cdc57c 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
@@ -78,6 +78,47 @@ int ip_route_me_harder(struct sk_buff **pskb) | |||
78 | } | 78 | } |
79 | EXPORT_SYMBOL(ip_route_me_harder); | 79 | EXPORT_SYMBOL(ip_route_me_harder); |
80 | 80 | ||
81 | #ifdef CONFIG_XFRM | ||
82 | int ip_xfrm_me_harder(struct sk_buff **pskb) | ||
83 | { | ||
84 | struct flowi fl; | ||
85 | unsigned int hh_len; | ||
86 | struct dst_entry *dst; | ||
87 | |||
88 | if (IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED) | ||
89 | return 0; | ||
90 | if (xfrm_decode_session(*pskb, &fl, AF_INET) < 0) | ||
91 | return -1; | ||
92 | |||
93 | dst = (*pskb)->dst; | ||
94 | if (dst->xfrm) | ||
95 | dst = ((struct xfrm_dst *)dst)->route; | ||
96 | dst_hold(dst); | ||
97 | |||
98 | if (xfrm_lookup(&dst, &fl, (*pskb)->sk, 0) < 0) | ||
99 | return -1; | ||
100 | |||
101 | dst_release((*pskb)->dst); | ||
102 | (*pskb)->dst = dst; | ||
103 | |||
104 | /* Change in oif may mean change in hh_len. */ | ||
105 | hh_len = (*pskb)->dst->dev->hard_header_len; | ||
106 | if (skb_headroom(*pskb) < hh_len) { | ||
107 | struct sk_buff *nskb; | ||
108 | |||
109 | nskb = skb_realloc_headroom(*pskb, hh_len); | ||
110 | if (!nskb) | ||
111 | return -1; | ||
112 | if ((*pskb)->sk) | ||
113 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
114 | kfree_skb(*pskb); | ||
115 | *pskb = nskb; | ||
116 | } | ||
117 | return 0; | ||
118 | } | ||
119 | EXPORT_SYMBOL(ip_xfrm_me_harder); | ||
120 | #endif | ||
121 | |||
81 | void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *); | 122 | void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *); |
82 | EXPORT_SYMBOL(ip_nat_decode_session); | 123 | EXPORT_SYMBOL(ip_nat_decode_session); |
83 | 124 | ||
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index afe3d8f817..7d7ab94a7a 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -771,7 +771,7 @@ static int get_entries(const struct arpt_get_entries *entries, | |||
771 | struct arpt_table *t; | 771 | struct arpt_table *t; |
772 | 772 | ||
773 | t = xt_find_table_lock(NF_ARP, entries->name); | 773 | t = xt_find_table_lock(NF_ARP, entries->name); |
774 | if (t || !IS_ERR(t)) { | 774 | if (t && !IS_ERR(t)) { |
775 | struct xt_table_info *private = t->private; | 775 | struct xt_table_info *private = t->private; |
776 | duprintf("t->private->number = %u\n", | 776 | duprintf("t->private->number = %u\n", |
777 | private->number); | 777 | private->number); |
@@ -807,6 +807,13 @@ static int do_replace(void __user *user, unsigned int len) | |||
807 | if (len != sizeof(tmp) + tmp.size) | 807 | if (len != sizeof(tmp) + tmp.size) |
808 | return -ENOPROTOOPT; | 808 | return -ENOPROTOOPT; |
809 | 809 | ||
810 | /* overflow check */ | ||
811 | if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS - | ||
812 | SMP_CACHE_BYTES) | ||
813 | return -ENOMEM; | ||
814 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) | ||
815 | return -ENOMEM; | ||
816 | |||
810 | newinfo = xt_alloc_table_info(tmp.size); | 817 | newinfo = xt_alloc_table_info(tmp.size); |
811 | if (!newinfo) | 818 | if (!newinfo) |
812 | return -ENOMEM; | 819 | return -ENOMEM; |
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index c9ebbe0d2d..e0b5926c76 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c | |||
@@ -1216,7 +1216,7 @@ static int ctnetlink_expect_event(struct notifier_block *this, | |||
1216 | 1216 | ||
1217 | b = skb->tail; | 1217 | b = skb->tail; |
1218 | 1218 | ||
1219 | type |= NFNL_SUBSYS_CTNETLINK << 8; | 1219 | type |= NFNL_SUBSYS_CTNETLINK_EXP << 8; |
1220 | nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg)); | 1220 | nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg)); |
1221 | nfmsg = NLMSG_DATA(nlh); | 1221 | nfmsg = NLMSG_DATA(nlh); |
1222 | 1222 | ||
@@ -1567,6 +1567,7 @@ static struct nfnetlink_subsystem ctnl_exp_subsys = { | |||
1567 | }; | 1567 | }; |
1568 | 1568 | ||
1569 | MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK); | 1569 | MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK); |
1570 | MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP); | ||
1570 | 1571 | ||
1571 | static int __init ctnetlink_init(void) | 1572 | static int __init ctnetlink_init(void) |
1572 | { | 1573 | { |
diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c index d3c5a371f9..4ba4463cec 100644 --- a/net/ipv4/netfilter/ip_conntrack_tftp.c +++ b/net/ipv4/netfilter/ip_conntrack_tftp.c | |||
@@ -71,6 +71,7 @@ static int tftp_help(struct sk_buff **pskb, | |||
71 | 71 | ||
72 | exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple; | 72 | exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple; |
73 | exp->mask.src.ip = 0xffffffff; | 73 | exp->mask.src.ip = 0xffffffff; |
74 | exp->mask.src.u.udp.port = 0; | ||
74 | exp->mask.dst.ip = 0xffffffff; | 75 | exp->mask.dst.ip = 0xffffffff; |
75 | exp->mask.dst.u.udp.port = 0xffff; | 76 | exp->mask.dst.u.udp.port = 0xffff; |
76 | exp->mask.dst.protonum = 0xff; | 77 | exp->mask.dst.protonum = 0xff; |
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index c1a6146250..1741d555ad 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c | |||
@@ -434,6 +434,7 @@ int ip_nat_icmp_reply_translation(struct sk_buff **pskb, | |||
434 | } *inside; | 434 | } *inside; |
435 | struct ip_conntrack_tuple inner, target; | 435 | struct ip_conntrack_tuple inner, target; |
436 | int hdrlen = (*pskb)->nh.iph->ihl * 4; | 436 | int hdrlen = (*pskb)->nh.iph->ihl * 4; |
437 | unsigned long statusbit; | ||
437 | 438 | ||
438 | if (!skb_make_writable(pskb, hdrlen + sizeof(*inside))) | 439 | if (!skb_make_writable(pskb, hdrlen + sizeof(*inside))) |
439 | return 0; | 440 | return 0; |
@@ -495,17 +496,16 @@ int ip_nat_icmp_reply_translation(struct sk_buff **pskb, | |||
495 | 496 | ||
496 | /* Change outer to look the reply to an incoming packet | 497 | /* Change outer to look the reply to an incoming packet |
497 | * (proto 0 means don't invert per-proto part). */ | 498 | * (proto 0 means don't invert per-proto part). */ |
499 | if (manip == IP_NAT_MANIP_SRC) | ||
500 | statusbit = IPS_SRC_NAT; | ||
501 | else | ||
502 | statusbit = IPS_DST_NAT; | ||
498 | 503 | ||
499 | /* Obviously, we need to NAT destination IP, but source IP | 504 | /* Invert if this is reply dir. */ |
500 | should be NAT'ed only if it is from a NAT'd host. | 505 | if (dir == IP_CT_DIR_REPLY) |
506 | statusbit ^= IPS_NAT_MASK; | ||
501 | 507 | ||
502 | Explanation: some people use NAT for anonymizing. Also, | 508 | if (ct->status & statusbit) { |
503 | CERT recommends dropping all packets from private IP | ||
504 | addresses (although ICMP errors from internal links with | ||
505 | such addresses are not too uncommon, as Alan Cox points | ||
506 | out) */ | ||
507 | if (manip != IP_NAT_MANIP_SRC | ||
508 | || ((*pskb)->nh.iph->saddr == ct->tuplehash[dir].tuple.src.ip)) { | ||
509 | invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); | 509 | invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); |
510 | if (!manip_pkt(0, pskb, 0, &target, manip)) | 510 | if (!manip_pkt(0, pskb, 0, &target, manip)) |
511 | return 0; | 511 | return 0; |
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index ad438fb185..ab1f88fa21 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c | |||
@@ -200,20 +200,14 @@ ip_nat_in(unsigned int hooknum, | |||
200 | const struct net_device *out, | 200 | const struct net_device *out, |
201 | int (*okfn)(struct sk_buff *)) | 201 | int (*okfn)(struct sk_buff *)) |
202 | { | 202 | { |
203 | struct ip_conntrack *ct; | ||
204 | enum ip_conntrack_info ctinfo; | ||
205 | unsigned int ret; | 203 | unsigned int ret; |
204 | u_int32_t daddr = (*pskb)->nh.iph->daddr; | ||
206 | 205 | ||
207 | ret = ip_nat_fn(hooknum, pskb, in, out, okfn); | 206 | ret = ip_nat_fn(hooknum, pskb, in, out, okfn); |
208 | if (ret != NF_DROP && ret != NF_STOLEN | 207 | if (ret != NF_DROP && ret != NF_STOLEN |
209 | && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) { | 208 | && daddr != (*pskb)->nh.iph->daddr) { |
210 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 209 | dst_release((*pskb)->dst); |
211 | 210 | (*pskb)->dst = NULL; | |
212 | if (ct->tuplehash[dir].tuple.src.ip != | ||
213 | ct->tuplehash[!dir].tuple.dst.ip) { | ||
214 | dst_release((*pskb)->dst); | ||
215 | (*pskb)->dst = NULL; | ||
216 | } | ||
217 | } | 211 | } |
218 | return ret; | 212 | return ret; |
219 | } | 213 | } |
@@ -235,19 +229,19 @@ ip_nat_out(unsigned int hooknum, | |||
235 | return NF_ACCEPT; | 229 | return NF_ACCEPT; |
236 | 230 | ||
237 | ret = ip_nat_fn(hooknum, pskb, in, out, okfn); | 231 | ret = ip_nat_fn(hooknum, pskb, in, out, okfn); |
232 | #ifdef CONFIG_XFRM | ||
238 | if (ret != NF_DROP && ret != NF_STOLEN | 233 | if (ret != NF_DROP && ret != NF_STOLEN |
239 | && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) { | 234 | && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) { |
240 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 235 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
241 | 236 | ||
242 | if (ct->tuplehash[dir].tuple.src.ip != | 237 | if (ct->tuplehash[dir].tuple.src.ip != |
243 | ct->tuplehash[!dir].tuple.dst.ip | 238 | ct->tuplehash[!dir].tuple.dst.ip |
244 | #ifdef CONFIG_XFRM | ||
245 | || ct->tuplehash[dir].tuple.src.u.all != | 239 | || ct->tuplehash[dir].tuple.src.u.all != |
246 | ct->tuplehash[!dir].tuple.dst.u.all | 240 | ct->tuplehash[!dir].tuple.dst.u.all |
247 | #endif | ||
248 | ) | 241 | ) |
249 | return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; | 242 | return ip_xfrm_me_harder(pskb) == 0 ? ret : NF_DROP; |
250 | } | 243 | } |
244 | #endif | ||
251 | return ret; | 245 | return ret; |
252 | } | 246 | } |
253 | 247 | ||
@@ -276,7 +270,7 @@ ip_nat_local_fn(unsigned int hooknum, | |||
276 | ct->tuplehash[!dir].tuple.src.ip | 270 | ct->tuplehash[!dir].tuple.src.ip |
277 | #ifdef CONFIG_XFRM | 271 | #ifdef CONFIG_XFRM |
278 | || ct->tuplehash[dir].tuple.dst.u.all != | 272 | || ct->tuplehash[dir].tuple.dst.u.all != |
279 | ct->tuplehash[dir].tuple.src.u.all | 273 | ct->tuplehash[!dir].tuple.src.u.all |
280 | #endif | 274 | #endif |
281 | ) | 275 | ) |
282 | return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; | 276 | return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; |
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 36339eb39e..08f80e2ea2 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c | |||
@@ -524,7 +524,7 @@ ipq_rcv_skb(struct sk_buff *skb) | |||
524 | write_unlock_bh(&queue_lock); | 524 | write_unlock_bh(&queue_lock); |
525 | 525 | ||
526 | status = ipq_receive_peer(NLMSG_DATA(nlh), type, | 526 | status = ipq_receive_peer(NLMSG_DATA(nlh), type, |
527 | skblen - NLMSG_LENGTH(0)); | 527 | nlmsglen - NLMSG_LENGTH(0)); |
528 | if (status < 0) | 528 | if (status < 0) |
529 | RCV_SKB_FAIL(status); | 529 | RCV_SKB_FAIL(status); |
530 | 530 | ||
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 2371b2062c..16f47c675f 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -921,6 +921,13 @@ do_replace(void __user *user, unsigned int len) | |||
921 | if (len != sizeof(tmp) + tmp.size) | 921 | if (len != sizeof(tmp) + tmp.size) |
922 | return -ENOPROTOOPT; | 922 | return -ENOPROTOOPT; |
923 | 923 | ||
924 | /* overflow check */ | ||
925 | if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS - | ||
926 | SMP_CACHE_BYTES) | ||
927 | return -ENOMEM; | ||
928 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) | ||
929 | return -ENOMEM; | ||
930 | |||
924 | newinfo = xt_alloc_table_info(tmp.size); | 931 | newinfo = xt_alloc_table_info(tmp.size); |
925 | if (!newinfo) | 932 | if (!newinfo) |
926 | return -ENOMEM; | 933 | return -ENOMEM; |
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index 6606ddb66a..cc27545ff9 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c | |||
@@ -425,7 +425,12 @@ ipt_log_target(struct sk_buff **pskb, | |||
425 | li.u.log.level = loginfo->level; | 425 | li.u.log.level = loginfo->level; |
426 | li.u.log.logflags = loginfo->logflags; | 426 | li.u.log.logflags = loginfo->logflags; |
427 | 427 | ||
428 | nf_log_packet(PF_INET, hooknum, *pskb, in, out, &li, loginfo->prefix); | 428 | if (loginfo->logflags & IPT_LOG_NFLOG) |
429 | nf_log_packet(PF_INET, hooknum, *pskb, in, out, &li, | ||
430 | loginfo->prefix); | ||
431 | else | ||
432 | ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li, | ||
433 | loginfo->prefix); | ||
429 | 434 | ||
430 | return IPT_CONTINUE; | 435 | return IPT_CONTINUE; |
431 | } | 436 | } |
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index 641dbc4776..180a9ea57b 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c | |||
@@ -35,6 +35,10 @@ | |||
35 | * each nlgroup you are using, so the total kernel memory usage increases | 35 | * each nlgroup you are using, so the total kernel memory usage increases |
36 | * by that factor. | 36 | * by that factor. |
37 | * | 37 | * |
38 | * Actually you should use nlbufsiz a bit smaller than PAGE_SIZE, since | ||
39 | * nlbufsiz is used with alloc_skb, which adds another | ||
40 | * sizeof(struct skb_shared_info). Use NLMSG_GOODSIZE instead. | ||
41 | * | ||
38 | * flushtimeout: | 42 | * flushtimeout: |
39 | * Specify, after how many hundredths of a second the queue should be | 43 | * Specify, after how many hundredths of a second the queue should be |
40 | * flushed even if it is not full yet. | 44 | * flushed even if it is not full yet. |
@@ -76,7 +80,7 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NFLOG); | |||
76 | 80 | ||
77 | #define PRINTR(format, args...) do { if (net_ratelimit()) printk(format , ## args); } while (0) | 81 | #define PRINTR(format, args...) do { if (net_ratelimit()) printk(format , ## args); } while (0) |
78 | 82 | ||
79 | static unsigned int nlbufsiz = 4096; | 83 | static unsigned int nlbufsiz = NLMSG_GOODSIZE; |
80 | module_param(nlbufsiz, uint, 0400); | 84 | module_param(nlbufsiz, uint, 0400); |
81 | MODULE_PARM_DESC(nlbufsiz, "netlink buffer size"); | 85 | MODULE_PARM_DESC(nlbufsiz, "netlink buffer size"); |
82 | 86 | ||
@@ -143,22 +147,26 @@ static void ulog_timer(unsigned long data) | |||
143 | static struct sk_buff *ulog_alloc_skb(unsigned int size) | 147 | static struct sk_buff *ulog_alloc_skb(unsigned int size) |
144 | { | 148 | { |
145 | struct sk_buff *skb; | 149 | struct sk_buff *skb; |
150 | unsigned int n; | ||
146 | 151 | ||
147 | /* alloc skb which should be big enough for a whole | 152 | /* alloc skb which should be big enough for a whole |
148 | * multipart message. WARNING: has to be <= 131000 | 153 | * multipart message. WARNING: has to be <= 131000 |
149 | * due to slab allocator restrictions */ | 154 | * due to slab allocator restrictions */ |
150 | 155 | ||
151 | skb = alloc_skb(nlbufsiz, GFP_ATOMIC); | 156 | n = max(size, nlbufsiz); |
157 | skb = alloc_skb(n, GFP_ATOMIC); | ||
152 | if (!skb) { | 158 | if (!skb) { |
153 | PRINTR("ipt_ULOG: can't alloc whole buffer %ub!\n", | 159 | PRINTR("ipt_ULOG: can't alloc whole buffer %ub!\n", n); |
154 | nlbufsiz); | ||
155 | 160 | ||
156 | /* try to allocate only as much as we need for | 161 | if (n > size) { |
157 | * current packet */ | 162 | /* try to allocate only as much as we need for |
163 | * current packet */ | ||
158 | 164 | ||
159 | skb = alloc_skb(size, GFP_ATOMIC); | 165 | skb = alloc_skb(size, GFP_ATOMIC); |
160 | if (!skb) | 166 | if (!skb) |
161 | PRINTR("ipt_ULOG: can't even allocate %ub\n", size); | 167 | PRINTR("ipt_ULOG: can't even allocate %ub\n", |
168 | size); | ||
169 | } | ||
162 | } | 170 | } |
163 | 171 | ||
164 | return skb; | 172 | return skb; |
diff --git a/net/ipv4/netfilter/ipt_policy.c b/net/ipv4/netfilter/ipt_policy.c index 18ca8258a1..5a7a265280 100644 --- a/net/ipv4/netfilter/ipt_policy.c +++ b/net/ipv4/netfilter/ipt_policy.c | |||
@@ -26,10 +26,13 @@ MODULE_LICENSE("GPL"); | |||
26 | static inline int | 26 | static inline int |
27 | match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e) | 27 | match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e) |
28 | { | 28 | { |
29 | #define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x)) | 29 | #define MATCH_ADDR(x,y,z) (!e->match.x || \ |
30 | ((e->x.a4.s_addr == (e->y.a4.s_addr & (z))) \ | ||
31 | ^ e->invert.x)) | ||
32 | #define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x)) | ||
30 | 33 | ||
31 | return MATCH(saddr, x->props.saddr.a4 & e->smask) && | 34 | return MATCH_ADDR(saddr, smask, x->props.saddr.a4) && |
32 | MATCH(daddr, x->id.daddr.a4 & e->dmask) && | 35 | MATCH_ADDR(daddr, dmask, x->id.daddr.a4) && |
33 | MATCH(proto, x->id.proto) && | 36 | MATCH(proto, x->id.proto) && |
34 | MATCH(mode, x->props.mode) && | 37 | MATCH(mode, x->props.mode) && |
35 | MATCH(spi, x->id.spi) && | 38 | MATCH(spi, x->id.spi) && |
@@ -89,7 +92,7 @@ match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info) | |||
89 | return 0; | 92 | return 0; |
90 | } | 93 | } |
91 | 94 | ||
92 | return strict ? 1 : 0; | 95 | return strict ? i == info->len : 0; |
93 | } | 96 | } |
94 | 97 | ||
95 | static int match(const struct sk_buff *skb, | 98 | static int match(const struct sk_buff *skb, |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 167619f638..6c8624a549 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
@@ -529,15 +529,10 @@ static int init_or_cleanup(int init) | |||
529 | goto cleanup_localinops; | 529 | goto cleanup_localinops; |
530 | } | 530 | } |
531 | #endif | 531 | #endif |
532 | |||
533 | /* For use by REJECT target */ | ||
534 | ip_ct_attach = __nf_conntrack_attach; | ||
535 | |||
536 | return ret; | 532 | return ret; |
537 | 533 | ||
538 | cleanup: | 534 | cleanup: |
539 | synchronize_net(); | 535 | synchronize_net(); |
540 | ip_ct_attach = NULL; | ||
541 | #ifdef CONFIG_SYSCTL | 536 | #ifdef CONFIG_SYSCTL |
542 | unregister_sysctl_table(nf_ct_ipv4_sysctl_header); | 537 | unregister_sysctl_table(nf_ct_ipv4_sysctl_header); |
543 | cleanup_localinops: | 538 | cleanup_localinops: |
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 39d49dc333..1b167c4bb3 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c | |||
@@ -49,7 +49,7 @@ static int fold_prot_inuse(struct proto *proto) | |||
49 | int res = 0; | 49 | int res = 0; |
50 | int cpu; | 50 | int cpu; |
51 | 51 | ||
52 | for (cpu = 0; cpu < NR_CPUS; cpu++) | 52 | for_each_cpu(cpu) |
53 | res += proto->stats[cpu].inuse; | 53 | res += proto->stats[cpu].inuse; |
54 | 54 | ||
55 | return res; | 55 | return res; |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index d82c242ea7..fca5fe0cf9 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -835,7 +835,7 @@ static int rt_garbage_collect(void) | |||
835 | int r; | 835 | int r; |
836 | 836 | ||
837 | rthp = rt_remove_balanced_route( | 837 | rthp = rt_remove_balanced_route( |
838 | &rt_hash_table[i].chain, | 838 | &rt_hash_table[k].chain, |
839 | rth, | 839 | rth, |
840 | &r); | 840 | &r); |
841 | goal -= r; | 841 | goal -= r; |
diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c index 63cf7e5408..e0e9d1383c 100644 --- a/net/ipv4/tcp_highspeed.c +++ b/net/ipv4/tcp_highspeed.c | |||
@@ -125,7 +125,7 @@ static void hstcp_cong_avoid(struct sock *sk, u32 adk, u32 rtt, | |||
125 | /* Update AIMD parameters */ | 125 | /* Update AIMD parameters */ |
126 | if (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd) { | 126 | if (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd) { |
127 | while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd && | 127 | while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd && |
128 | ca->ai < HSTCP_AIMD_MAX) | 128 | ca->ai < HSTCP_AIMD_MAX - 1) |
129 | ca->ai++; | 129 | ca->ai++; |
130 | } else if (tp->snd_cwnd < hstcp_aimd_vals[ca->ai].cwnd) { | 130 | } else if (tp->snd_cwnd < hstcp_aimd_vals[ca->ai].cwnd) { |
131 | while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd && | 131 | while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd && |
diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c index 3284cfb993..128de4d7c0 100644 --- a/net/ipv4/tcp_htcp.c +++ b/net/ipv4/tcp_htcp.c | |||
@@ -230,7 +230,6 @@ static void htcp_cong_avoid(struct sock *sk, u32 ack, u32 rtt, | |||
230 | if (tp->snd_cwnd < tp->snd_cwnd_clamp) | 230 | if (tp->snd_cwnd < tp->snd_cwnd_clamp) |
231 | tp->snd_cwnd++; | 231 | tp->snd_cwnd++; |
232 | tp->snd_cwnd_cnt = 0; | 232 | tp->snd_cwnd_cnt = 0; |
233 | ca->ccount++; | ||
234 | } | 233 | } |
235 | } | 234 | } |
236 | } | 235 | } |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a97ed5416c..e9a54ae7d6 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -456,7 +456,8 @@ void tcp_rcv_space_adjust(struct sock *sk) | |||
456 | 456 | ||
457 | tp->rcvq_space.space = space; | 457 | tp->rcvq_space.space = space; |
458 | 458 | ||
459 | if (sysctl_tcp_moderate_rcvbuf) { | 459 | if (sysctl_tcp_moderate_rcvbuf && |
460 | !(sk->sk_userlocks & SOCK_RCVBUF_LOCK)) { | ||
460 | int new_clamp = space; | 461 | int new_clamp = space; |
461 | 462 | ||
462 | /* Receive space grows, normalize in order to | 463 | /* Receive space grows, normalize in order to |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 6ea353907a..233bdf2599 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -236,7 +236,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
236 | if (err) | 236 | if (err) |
237 | goto failure; | 237 | goto failure; |
238 | 238 | ||
239 | err = ip_route_newports(&rt, inet->sport, inet->dport, sk); | 239 | err = ip_route_newports(&rt, IPPROTO_TCP, inet->sport, inet->dport, sk); |
240 | if (err) | 240 | if (err) |
241 | goto failure; | 241 | goto failure; |
242 | 242 | ||
@@ -1845,7 +1845,6 @@ void __init tcp_v4_init(struct net_proto_family *ops) | |||
1845 | } | 1845 | } |
1846 | 1846 | ||
1847 | EXPORT_SYMBOL(ipv4_specific); | 1847 | EXPORT_SYMBOL(ipv4_specific); |
1848 | EXPORT_SYMBOL(inet_bind_bucket_create); | ||
1849 | EXPORT_SYMBOL(tcp_hashinfo); | 1848 | EXPORT_SYMBOL(tcp_hashinfo); |
1850 | EXPORT_SYMBOL(tcp_prot); | 1849 | EXPORT_SYMBOL(tcp_prot); |
1851 | EXPORT_SYMBOL(tcp_unhash); | 1850 | EXPORT_SYMBOL(tcp_unhash); |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index a7623ead39..9f498a6c88 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -1036,6 +1036,10 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_ | |||
1036 | 1036 | ||
1037 | limit = min(send_win, cong_win); | 1037 | limit = min(send_win, cong_win); |
1038 | 1038 | ||
1039 | /* If a full-sized TSO skb can be sent, do it. */ | ||
1040 | if (limit >= 65536) | ||
1041 | return 0; | ||
1042 | |||
1039 | if (sysctl_tcp_tso_win_divisor) { | 1043 | if (sysctl_tcp_tso_win_divisor) { |
1040 | u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache); | 1044 | u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache); |
1041 | 1045 | ||
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index d4df0ddd42..32ad229b4f 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c | |||
@@ -152,10 +152,16 @@ error_nolock: | |||
152 | goto out_exit; | 152 | goto out_exit; |
153 | } | 153 | } |
154 | 154 | ||
155 | int xfrm4_output_finish(struct sk_buff *skb) | 155 | static int xfrm4_output_finish(struct sk_buff *skb) |
156 | { | 156 | { |
157 | int err; | 157 | int err; |
158 | 158 | ||
159 | #ifdef CONFIG_NETFILTER | ||
160 | if (!skb->dst->xfrm) { | ||
161 | IPCB(skb)->flags |= IPSKB_REROUTED; | ||
162 | return dst_output(skb); | ||
163 | } | ||
164 | #endif | ||
159 | while (likely((err = xfrm4_output_one(skb)) == 0)) { | 165 | while (likely((err = xfrm4_output_one(skb)) == 0)) { |
160 | nf_reset(skb); | 166 | nf_reset(skb); |
161 | 167 | ||
@@ -178,6 +184,7 @@ int xfrm4_output_finish(struct sk_buff *skb) | |||
178 | 184 | ||
179 | int xfrm4_output(struct sk_buff *skb) | 185 | int xfrm4_output(struct sk_buff *skb) |
180 | { | 186 | { |
181 | return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev, | 187 | return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev, |
182 | xfrm4_output_finish); | 188 | xfrm4_output_finish, |
189 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | ||
183 | } | 190 | } |
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 42196ba3b0..f285bbf296 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c | |||
@@ -8,7 +8,6 @@ | |||
8 | * | 8 | * |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <asm/bug.h> | ||
12 | #include <linux/compiler.h> | 11 | #include <linux/compiler.h> |
13 | #include <linux/config.h> | 12 | #include <linux/config.h> |
14 | #include <linux/inetdevice.h> | 13 | #include <linux/inetdevice.h> |
@@ -36,6 +35,7 @@ __xfrm4_find_bundle(struct flowi *fl, struct xfrm_policy *policy) | |||
36 | if (xdst->u.rt.fl.oif == fl->oif && /*XXX*/ | 35 | if (xdst->u.rt.fl.oif == fl->oif && /*XXX*/ |
37 | xdst->u.rt.fl.fl4_dst == fl->fl4_dst && | 36 | xdst->u.rt.fl.fl4_dst == fl->fl4_dst && |
38 | xdst->u.rt.fl.fl4_src == fl->fl4_src && | 37 | xdst->u.rt.fl.fl4_src == fl->fl4_src && |
38 | xdst->u.rt.fl.fl4_tos == fl->fl4_tos && | ||
39 | xfrm_bundle_ok(xdst, fl, AF_INET)) { | 39 | xfrm_bundle_ok(xdst, fl, AF_INET)) { |
40 | dst_clone(dst); | 40 | dst_clone(dst); |
41 | break; | 41 | break; |
@@ -62,7 +62,8 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int | |||
62 | .nl_u = { | 62 | .nl_u = { |
63 | .ip4_u = { | 63 | .ip4_u = { |
64 | .saddr = local, | 64 | .saddr = local, |
65 | .daddr = remote | 65 | .daddr = remote, |
66 | .tos = fl->fl4_tos | ||
66 | } | 67 | } |
67 | } | 68 | } |
68 | }; | 69 | }; |
@@ -231,6 +232,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl) | |||
231 | fl->proto = iph->protocol; | 232 | fl->proto = iph->protocol; |
232 | fl->fl4_dst = iph->daddr; | 233 | fl->fl4_dst = iph->daddr; |
233 | fl->fl4_src = iph->saddr; | 234 | fl->fl4_src = iph->saddr; |
235 | fl->fl4_tos = iph->tos; | ||
234 | } | 236 | } |
235 | 237 | ||
236 | static inline int xfrm4_garbage_collect(void) | 238 | static inline int xfrm4_garbage_collect(void) |