diff options
Diffstat (limited to 'net/ipv4/ip_output.c')
-rw-r--r-- | net/ipv4/ip_output.c | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index d1bcc9f21d4f..9a4a6c96cb0d 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -96,8 +96,8 @@ int __ip_local_out(struct sk_buff *skb) | |||
96 | 96 | ||
97 | iph->tot_len = htons(skb->len); | 97 | iph->tot_len = htons(skb->len); |
98 | ip_send_check(iph); | 98 | ip_send_check(iph); |
99 | return nf_hook(PF_INET, NF_INET_LOCAL_OUT, skb, NULL, skb_dst(skb)->dev, | 99 | return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, skb, NULL, |
100 | dst_output); | 100 | skb_dst(skb)->dev, dst_output); |
101 | } | 101 | } |
102 | 102 | ||
103 | int ip_local_out(struct sk_buff *skb) | 103 | int ip_local_out(struct sk_buff *skb) |
@@ -272,8 +272,8 @@ int ip_mc_output(struct sk_buff *skb) | |||
272 | ) { | 272 | ) { |
273 | struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); | 273 | struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); |
274 | if (newskb) | 274 | if (newskb) |
275 | NF_HOOK(PF_INET, NF_INET_POST_ROUTING, newskb, | 275 | NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, |
276 | NULL, newskb->dev, | 276 | newskb, NULL, newskb->dev, |
277 | ip_dev_loopback_xmit); | 277 | ip_dev_loopback_xmit); |
278 | } | 278 | } |
279 | 279 | ||
@@ -288,12 +288,12 @@ int ip_mc_output(struct sk_buff *skb) | |||
288 | if (rt->rt_flags&RTCF_BROADCAST) { | 288 | if (rt->rt_flags&RTCF_BROADCAST) { |
289 | struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); | 289 | struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); |
290 | if (newskb) | 290 | if (newskb) |
291 | NF_HOOK(PF_INET, NF_INET_POST_ROUTING, newskb, NULL, | 291 | NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, newskb, |
292 | newskb->dev, ip_dev_loopback_xmit); | 292 | NULL, newskb->dev, ip_dev_loopback_xmit); |
293 | } | 293 | } |
294 | 294 | ||
295 | return NF_HOOK_COND(PF_INET, NF_INET_POST_ROUTING, skb, NULL, skb->dev, | 295 | return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, NULL, |
296 | ip_finish_output, | 296 | skb->dev, ip_finish_output, |
297 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | 297 | !(IPCB(skb)->flags & IPSKB_REROUTED)); |
298 | } | 298 | } |
299 | 299 | ||
@@ -306,22 +306,24 @@ int ip_output(struct sk_buff *skb) | |||
306 | skb->dev = dev; | 306 | skb->dev = dev; |
307 | skb->protocol = htons(ETH_P_IP); | 307 | skb->protocol = htons(ETH_P_IP); |
308 | 308 | ||
309 | return NF_HOOK_COND(PF_INET, NF_INET_POST_ROUTING, skb, NULL, dev, | 309 | return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, NULL, dev, |
310 | ip_finish_output, | 310 | ip_finish_output, |
311 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | 311 | !(IPCB(skb)->flags & IPSKB_REROUTED)); |
312 | } | 312 | } |
313 | 313 | ||
314 | int ip_queue_xmit(struct sk_buff *skb, int ipfragok) | 314 | int ip_queue_xmit(struct sk_buff *skb) |
315 | { | 315 | { |
316 | struct sock *sk = skb->sk; | 316 | struct sock *sk = skb->sk; |
317 | struct inet_sock *inet = inet_sk(sk); | 317 | struct inet_sock *inet = inet_sk(sk); |
318 | struct ip_options *opt = inet->opt; | 318 | struct ip_options *opt = inet->opt; |
319 | struct rtable *rt; | 319 | struct rtable *rt; |
320 | struct iphdr *iph; | 320 | struct iphdr *iph; |
321 | int res; | ||
321 | 322 | ||
322 | /* Skip all of this if the packet is already routed, | 323 | /* Skip all of this if the packet is already routed, |
323 | * f.e. by something like SCTP. | 324 | * f.e. by something like SCTP. |
324 | */ | 325 | */ |
326 | rcu_read_lock(); | ||
325 | rt = skb_rtable(skb); | 327 | rt = skb_rtable(skb); |
326 | if (rt != NULL) | 328 | if (rt != NULL) |
327 | goto packet_routed; | 329 | goto packet_routed; |
@@ -359,7 +361,7 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok) | |||
359 | } | 361 | } |
360 | sk_setup_caps(sk, &rt->u.dst); | 362 | sk_setup_caps(sk, &rt->u.dst); |
361 | } | 363 | } |
362 | skb_dst_set(skb, dst_clone(&rt->u.dst)); | 364 | skb_dst_set_noref(skb, &rt->u.dst); |
363 | 365 | ||
364 | packet_routed: | 366 | packet_routed: |
365 | if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) | 367 | if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) |
@@ -370,7 +372,7 @@ packet_routed: | |||
370 | skb_reset_network_header(skb); | 372 | skb_reset_network_header(skb); |
371 | iph = ip_hdr(skb); | 373 | iph = ip_hdr(skb); |
372 | *((__be16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff)); | 374 | *((__be16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff)); |
373 | if (ip_dont_fragment(sk, &rt->u.dst) && !ipfragok) | 375 | if (ip_dont_fragment(sk, &rt->u.dst) && !skb->local_df) |
374 | iph->frag_off = htons(IP_DF); | 376 | iph->frag_off = htons(IP_DF); |
375 | else | 377 | else |
376 | iph->frag_off = 0; | 378 | iph->frag_off = 0; |
@@ -391,9 +393,12 @@ packet_routed: | |||
391 | skb->priority = sk->sk_priority; | 393 | skb->priority = sk->sk_priority; |
392 | skb->mark = sk->sk_mark; | 394 | skb->mark = sk->sk_mark; |
393 | 395 | ||
394 | return ip_local_out(skb); | 396 | res = ip_local_out(skb); |
397 | rcu_read_unlock(); | ||
398 | return res; | ||
395 | 399 | ||
396 | no_route: | 400 | no_route: |
401 | rcu_read_unlock(); | ||
397 | IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); | 402 | IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); |
398 | kfree_skb(skb); | 403 | kfree_skb(skb); |
399 | return -EHOSTUNREACH; | 404 | return -EHOSTUNREACH; |
@@ -469,6 +474,10 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
469 | 474 | ||
470 | hlen = iph->ihl * 4; | 475 | hlen = iph->ihl * 4; |
471 | mtu = dst_mtu(&rt->u.dst) - hlen; /* Size of data space */ | 476 | mtu = dst_mtu(&rt->u.dst) - hlen; /* Size of data space */ |
477 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
478 | if (skb->nf_bridge) | ||
479 | mtu -= nf_bridge_mtu_reduction(skb); | ||
480 | #endif | ||
472 | IPCB(skb)->flags |= IPSKB_FRAG_COMPLETE; | 481 | IPCB(skb)->flags |= IPSKB_FRAG_COMPLETE; |
473 | 482 | ||
474 | /* When frag_list is given, use it. First, check its validity: | 483 | /* When frag_list is given, use it. First, check its validity: |