aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ip_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/ip_output.c')
-rw-r--r--net/ipv4/ip_output.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 252897443ef9..9a4a6c96cb0d 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -318,10 +318,12 @@ int ip_queue_xmit(struct sk_buff *skb)
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)
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
364packet_routed: 366packet_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)
@@ -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
396no_route: 400no_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;