ipv4: Don't drop redirected route cache entry unless PTMU actually expired
[safe/jmp/linux-2.6] / net / ipv4 / icmp.c
index 3f50807..4b4c2bc 100644 (file)
@@ -114,7 +114,7 @@ struct icmp_bxm {
 /* An array of errno for error messages from dest unreach. */
 /* RFC 1122: 3.2.2.1 States that NET_UNREACH, HOST_UNREACH and SR_FAILED MUST be considered 'transient errs'. */
 
-struct icmp_err icmp_err_convert[] = {
+const struct icmp_err icmp_err_convert[] = {
        {
                .errno = ENETUNREACH,   /* ICMP_NET_UNREACH */
                .fatal = 0,
@@ -356,7 +356,7 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param,
 static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
 {
        struct ipcm_cookie ipc;
-       struct rtable *rt = skb->rtable;
+       struct rtable *rt = skb_rtable(skb);
        struct net *net = dev_net(rt->u.dst.dev);
        struct sock *sk;
        struct inet_sock *inet;
@@ -416,7 +416,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
        struct iphdr *iph;
        int room;
        struct icmp_bxm icmp_param;
-       struct rtable *rt = skb_in->rtable;
+       struct rtable *rt = skb_rtable(skb_in);
        struct ipcm_cookie ipc;
        __be32 saddr;
        u8  tos;
@@ -501,15 +501,16 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
        if (!(rt->rt_flags & RTCF_LOCAL)) {
                struct net_device *dev = NULL;
 
+               rcu_read_lock();
                if (rt->fl.iif &&
                        net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr)
-                       dev = dev_get_by_index(net, rt->fl.iif);
+                       dev = dev_get_by_index_rcu(net, rt->fl.iif);
 
-               if (dev) {
+               if (dev)
                        saddr = inet_select_addr(dev, 0, RT_SCOPE_LINK);
-                       dev_put(dev);
-               } else
+               else
                        saddr = 0;
+               rcu_read_unlock();
        }
 
        tos = icmp_pointers[type].error ? ((iph->tos & IPTOS_TOS_MASK) |
@@ -591,13 +592,13 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
                                goto relookup_failed;
 
                        /* Ugh! */
-                       odst = skb_in->dst;
+                       odst = skb_dst(skb_in);
                        err = ip_route_input(skb_in, fl.fl4_dst, fl.fl4_src,
                                             RT_TOS(tos), rt2->u.dst.dev);
 
                        dst_release(&rt2->u.dst);
-                       rt2 = skb_in->rtable;
-                       skb_in->dst = odst;
+                       rt2 = skb_rtable(skb_in);
+                       skb_dst_set(skb_in, odst);
                }
 
                if (err)
@@ -655,11 +656,11 @@ static void icmp_unreach(struct sk_buff *skb)
        struct iphdr *iph;
        struct icmphdr *icmph;
        int hash, protocol;
-       struct net_protocol *ipprot;
+       const struct net_protocol *ipprot;
        u32 info = 0;
        struct net *net;
 
-       net = dev_net(skb->dst->dev);
+       net = dev_net(skb_dst(skb)->dev);
 
        /*
         *      Incomplete header ?
@@ -822,7 +823,7 @@ static void icmp_echo(struct sk_buff *skb)
 {
        struct net *net;
 
-       net = dev_net(skb->dst->dev);
+       net = dev_net(skb_dst(skb)->dev);
        if (!net->ipv4.sysctl_icmp_echo_ignore_all) {
                struct icmp_bxm icmp_param;
 
@@ -873,7 +874,7 @@ static void icmp_timestamp(struct sk_buff *skb)
 out:
        return;
 out_err:
-       ICMP_INC_STATS_BH(dev_net(skb->dst->dev), ICMP_MIB_INERRORS);
+       ICMP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), ICMP_MIB_INERRORS);
        goto out;
 }
 
@@ -926,7 +927,7 @@ static void icmp_address(struct sk_buff *skb)
 
 static void icmp_address_reply(struct sk_buff *skb)
 {
-       struct rtable *rt = skb->rtable;
+       struct rtable *rt = skb_rtable(skb);
        struct net_device *dev = skb->dev;
        struct in_device *in_dev;
        struct in_ifaddr *ifa;
@@ -970,7 +971,7 @@ static void icmp_discard(struct sk_buff *skb)
 int icmp_rcv(struct sk_buff *skb)
 {
        struct icmphdr *icmph;
-       struct rtable *rt = skb->rtable;
+       struct rtable *rt = skb_rtable(skb);
        struct net *net = dev_net(rt->u.dst.dev);
 
        if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
@@ -1165,6 +1166,10 @@ static int __net_init icmp_sk_init(struct net *net)
                sk->sk_sndbuf =
                        (2 * ((64 * 1024) + sizeof(struct sk_buff)));
 
+               /*
+                * Speedup sock_wfree()
+                */
+               sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
                inet_sk(sk)->pmtudisc = IP_PMTUDISC_DONT;
        }