netns: selective flush of rt_cache
[safe/jmp/linux-2.6] / net / ipv4 / icmp.c
index 7049b3f..aa7cf46 100644 (file)
@@ -3,8 +3,6 @@
  *
  *             Alan Cox, <alan@redhat.com>
  *
- *     Version: $Id: icmp.c,v 1.85 2002/02/01 22:01:03 davem Exp $
- *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License
  *     as published by the Free Software Foundation; either version
@@ -93,6 +91,7 @@
 #include <asm/uaccess.h>
 #include <net/checksum.h>
 #include <net/xfrm.h>
+#include <net/inet_common.h>
 
 /*
  *     Build xmit assembly blocks
@@ -577,7 +576,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
                }
 
                if (xfrm_decode_session_reverse(skb_in, &fl, AF_INET))
-                       goto out_unlock;
+                       goto relookup_failed;
 
                if (inet_addr_type(net, fl.fl4_src) == RTN_LOCAL)
                        err = __ip_route_output_key(net, &rt2, &fl);
@@ -587,7 +586,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
 
                        fl2.fl4_dst = fl.fl4_src;
                        if (ip_route_output_key(net, &rt2, &fl2))
-                               goto out_unlock;
+                               goto relookup_failed;
 
                        /* Ugh! */
                        odst = skb_in->dst;
@@ -600,21 +599,23 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
                }
 
                if (err)
-                       goto out_unlock;
+                       goto relookup_failed;
 
                err = xfrm_lookup((struct dst_entry **)&rt2, &fl, NULL,
                                  XFRM_LOOKUP_ICMP);
-               if (err == -ENOENT) {
+               switch (err) {
+               case 0:
+                       dst_release(&rt->u.dst);
+                       rt = rt2;
+                       break;
+               case -EPERM:
+                       goto ende;
+               default:
+relookup_failed:
                        if (!rt)
                                goto out_unlock;
-                       goto route_done;
+                       break;
                }
-
-               dst_release(&rt->u.dst);
-               rt = rt2;
-
-               if (err)
-                       goto out_unlock;
        }
 
 route_done:
@@ -682,19 +683,20 @@ static void icmp_unreach(struct sk_buff *skb)
                        break;
                case ICMP_FRAG_NEEDED:
                        if (ipv4_config.no_pmtu_disc) {
-                               LIMIT_NETDEBUG(KERN_INFO "ICMP: %u.%u.%u.%u: "
+                               LIMIT_NETDEBUG(KERN_INFO "ICMP: " NIPQUAD_FMT ": "
                                                         "fragmentation needed "
                                                         "and DF set.\n",
                                               NIPQUAD(iph->daddr));
                        } else {
                                info = ip_rt_frag_needed(net, iph,
-                                                    ntohs(icmph->un.frag.mtu));
+                                                        ntohs(icmph->un.frag.mtu),
+                                                        skb->dev);
                                if (!info)
                                        goto out;
                        }
                        break;
                case ICMP_SR_FAILED:
-                       LIMIT_NETDEBUG(KERN_INFO "ICMP: %u.%u.%u.%u: Source "
+                       LIMIT_NETDEBUG(KERN_INFO "ICMP: " NIPQUAD_FMT ": Source "
                                                 "Route Failed.\n",
                                       NIPQUAD(iph->daddr));
                        break;
@@ -727,9 +729,9 @@ static void icmp_unreach(struct sk_buff *skb)
        if (!net->ipv4.sysctl_icmp_ignore_bogus_error_responses &&
            inet_addr_type(net, iph->daddr) == RTN_BROADCAST) {
                if (net_ratelimit())
-                       printk(KERN_WARNING "%u.%u.%u.%u sent an invalid ICMP "
+                       printk(KERN_WARNING NIPQUAD_FMT " sent an invalid ICMP "
                                            "type %u, code %u "
-                                           "error to a broadcast: %u.%u.%u.%u on %s\n",
+                                           "error to a broadcast: " NIPQUAD_FMT " on %s\n",
                               NIPQUAD(ip_hdr(skb)->saddr),
                               icmph->type, icmph->code,
                               NIPQUAD(iph->daddr),
@@ -821,7 +823,7 @@ static void icmp_echo(struct sk_buff *skb)
 {
        struct net *net;
 
-       net = skb->dst->dev->nd_net;
+       net = dev_net(skb->dst->dev);
        if (!net->ipv4.sysctl_icmp_echo_ignore_all) {
                struct icmp_bxm icmp_param;
 
@@ -844,7 +846,7 @@ static void icmp_echo(struct sk_buff *skb)
  */
 static void icmp_timestamp(struct sk_buff *skb)
 {
-       struct timeval tv;
+       struct timespec tv;
        struct icmp_bxm icmp_param;
        /*
         *      Too short.
@@ -855,9 +857,9 @@ static void icmp_timestamp(struct sk_buff *skb)
        /*
         *      Fill in the current time as ms since midnight UT:
         */
-       do_gettimeofday(&tv);
-       icmp_param.data.times[1] = htonl((tv.tv_sec % 86400) * 1000 +
-                                        tv.tv_usec / 1000);
+       getnstimeofday(&tv);
+       icmp_param.data.times[1] = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC +
+                                        tv.tv_nsec / NSEC_PER_MSEC);
        icmp_param.data.times[2] = icmp_param.data.times[1];
        if (skb_copy_bits(skb, 0, &icmp_param.data.times[0], 4))
                BUG();
@@ -950,8 +952,8 @@ static void icmp_address_reply(struct sk_buff *skb)
                                break;
                }
                if (!ifa && net_ratelimit()) {
-                       printk(KERN_INFO "Wrong address mask %u.%u.%u.%u from "
-                                        "%s/%u.%u.%u.%u\n",
+                       printk(KERN_INFO "Wrong address mask " NIPQUAD_FMT " from "
+                                        "%s/" NIPQUAD_FMT "\n",
                               NIPQUAD(*mp), dev->name, NIPQUAD(rt->rt_src));
                }
        }
@@ -1027,7 +1029,7 @@ int icmp_rcv(struct sk_buff *skb)
        if (rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) {
                struct net *net;
 
-               net = rt->u.dst.dev->nd_net;
+               net = dev_net(rt->u.dst.dev);
                /*
                 *      RFC 1122: 3.2.2.6 An ICMP_ECHO to broadcast MAY be
                 *        silently ignored (we let user decide with a sysctl).
@@ -1136,12 +1138,12 @@ static void __net_exit icmp_sk_exit(struct net *net)
        int i;
 
        for_each_possible_cpu(i)
-               sk_release_kernel(net->ipv4.icmp_sk[i]);
+               inet_ctl_sock_destroy(net->ipv4.icmp_sk[i]);
        kfree(net->ipv4.icmp_sk);
        net->ipv4.icmp_sk = NULL;
 }
 
-int __net_init icmp_sk_init(struct net *net)
+static int __net_init icmp_sk_init(struct net *net)
 {
        int i, err;
 
@@ -1152,17 +1154,13 @@ int __net_init icmp_sk_init(struct net *net)
 
        for_each_possible_cpu(i) {
                struct sock *sk;
-               struct socket *sock;
-               struct inet_sock *inet;
 
-               err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP, &sock);
+               err = inet_ctl_sock_create(&sk, PF_INET,
+                                          SOCK_RAW, IPPROTO_ICMP, net);
                if (err < 0)
                        goto fail;
 
-               net->ipv4.icmp_sk[i] = sk = sock->sk;
-               sk_change_net(sk, net);
-
-               sk->sk_allocation = GFP_ATOMIC;
+               net->ipv4.icmp_sk[i] = sk;
 
                /* Enough space for 2 64K ICMP packets, including
                 * sk_buff struct overhead.
@@ -1170,15 +1168,7 @@ int __net_init icmp_sk_init(struct net *net)
                sk->sk_sndbuf =
                        (2 * ((64 * 1024) + sizeof(struct sk_buff)));
 
-               inet = inet_sk(sk);
-               inet->uc_ttl = -1;
-               inet->pmtudisc = IP_PMTUDISC_DONT;
-
-               /* Unhash it so that IP input processing does not even
-                * see it, we do not wish this socket to see incoming
-                * packets.
-                */
-               sk->sk_prot->unhash(sk);
+               inet_sk(sk)->pmtudisc = IP_PMTUDISC_DONT;
        }
 
        /* Control parameters for ECHO replies. */
@@ -1208,7 +1198,7 @@ int __net_init icmp_sk_init(struct net *net)
 
 fail:
        for_each_possible_cpu(i)
-               sk_release_kernel(net->ipv4.icmp_sk[i]);
+               inet_ctl_sock_destroy(net->ipv4.icmp_sk[i]);
        kfree(net->ipv4.icmp_sk);
        return err;
 }