]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv4/icmp.c
mac80211: add mesh interface type
[linux-2.6-omap-h63xx.git] / net / ipv4 / icmp.c
index 9bcf263f06cac8887d893f9e7240d039c3c113a1..ff9a8e643fccbe1ee08e76f9190b6409bd07cc59 100644 (file)
@@ -229,8 +229,10 @@ static const struct icmp_control icmp_pointers[NR_ICMP_TYPES+1];
  *
  *     On SMP we have one ICMP socket per-cpu.
  */
-static DEFINE_PER_CPU(struct sock *, __icmp_sk) = NULL;
-#define icmp_sk                __get_cpu_var(__icmp_sk)
+static struct sock *icmp_sk(struct net *net)
+{
+       return net->ipv4.icmp_sk[smp_processor_id()];
+}
 
 static inline int icmp_xmit_lock(struct sock *sk)
 {
@@ -349,7 +351,7 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param,
        struct sock *sk;
        struct sk_buff *skb;
 
-       sk = icmp_sk;
+       sk = icmp_sk(rt->u.dst.dev->nd_net);
        if (ip_append_data(sk, icmp_glue_bits, icmp_param,
                           icmp_param->data_len+icmp_param->head_len,
                           icmp_param->head_len,
@@ -378,10 +380,11 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param,
 
 static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
 {
-       struct sock *sk = icmp_sk;
-       struct inet_sock *inet = inet_sk(sk);
        struct ipcm_cookie ipc;
-       struct rtable *rt = (struct rtable *)skb->dst;
+       struct rtable *rt = skb->rtable;
+       struct net *net = rt->u.dst.dev->nd_net;
+       struct sock *sk = icmp_sk(net);
+       struct inet_sock *inet = inet_sk(sk);
        __be32 daddr;
 
        if (ip_options_echo(&icmp_param->replyopts, skb))
@@ -407,7 +410,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
                                                .tos = RT_TOS(ip_hdr(skb)->tos) } },
                                    .proto = IPPROTO_ICMP };
                security_skb_classify_flow(skb, &fl);
-               if (ip_route_output_key(rt->u.dst.dev->nd_net, &rt, &fl))
+               if (ip_route_output_key(net, &rt, &fl))
                        goto out_unlock;
        }
        if (icmpv4_xrlim_allow(rt, icmp_param->data.icmph.type,
@@ -435,16 +438,17 @@ 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 = (struct rtable *)skb_in->dst;
+       struct rtable *rt = skb_in->rtable;
        struct ipcm_cookie ipc;
        __be32 saddr;
        u8  tos;
        struct net *net;
-       struct sock *sk = icmp_sk;
+       struct sock *sk;
 
        if (!rt)
                goto out;
        net = rt->u.dst.dev->nd_net;
+       sk = icmp_sk(net);
 
        /*
         *      Find the original header. It is expected to be valid, of course.
@@ -612,7 +616,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
                                             RT_TOS(tos), rt2->u.dst.dev);
 
                        dst_release(&rt2->u.dst);
-                       rt2 = (struct rtable *)skb_in->dst;
+                       rt2 = skb_in->rtable;
                        skb_in->dst = odst;
                }
 
@@ -939,7 +943,7 @@ static void icmp_address(struct sk_buff *skb)
 
 static void icmp_address_reply(struct sk_buff *skb)
 {
-       struct rtable *rt = (struct rtable *)skb->dst;
+       struct rtable *rt = skb->rtable;
        struct net_device *dev = skb->dev;
        struct in_device *in_dev;
        struct in_ifaddr *ifa;
@@ -984,7 +988,7 @@ static void icmp_discard(struct sk_buff *skb)
 int icmp_rcv(struct sk_buff *skb)
 {
        struct icmphdr *icmph;
-       struct rtable *rt = (struct rtable *)skb->dst;
+       struct rtable *rt = skb->rtable;
 
        if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
                int nh;
@@ -1142,25 +1146,25 @@ static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = {
        },
 };
 
-static void __exit icmp_exit(void)
+static void __net_exit icmp_sk_exit(struct net *net)
 {
        int i;
 
-       for_each_possible_cpu(i) {
-               struct sock *sk;
-
-               sk = per_cpu(__icmp_sk, i);
-               if (sk == NULL)
-                       continue;
-               per_cpu(__icmp_sk, i) = NULL;
-               sock_release(sk->sk_socket);
-       }
+       for_each_possible_cpu(i)
+               sk_release_kernel(net->ipv4.icmp_sk[i]);
+       kfree(net->ipv4.icmp_sk);
+       net->ipv4.icmp_sk = NULL;
 }
 
-int __init icmp_init(void)
+int __net_init icmp_sk_init(struct net *net)
 {
        int i, err;
 
+       net->ipv4.icmp_sk =
+               kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL);
+       if (net->ipv4.icmp_sk == NULL)
+               return -ENOMEM;
+
        for_each_possible_cpu(i) {
                struct sock *sk;
                struct socket *sock;
@@ -1170,7 +1174,9 @@ int __init icmp_init(void)
                if (err < 0)
                        goto fail;
 
-               per_cpu(__icmp_sk, i) = sk = sock->sk;
+               net->ipv4.icmp_sk[i] = sk = sock->sk;
+               sk_change_net(sk, net);
+
                sk->sk_allocation = GFP_ATOMIC;
 
                /* Enough space for 2 64K ICMP packets, including
@@ -1192,10 +1198,22 @@ int __init icmp_init(void)
        return 0;
 
 fail:
-       icmp_exit();
+       for_each_possible_cpu(i)
+               sk_release_kernel(net->ipv4.icmp_sk[i]);
+       kfree(net->ipv4.icmp_sk);
        return err;
 }
 
+static struct pernet_operations __net_initdata icmp_sk_ops = {
+       .init = icmp_sk_init,
+       .exit = icmp_sk_exit,
+};
+
+int __init icmp_init(void)
+{
+       return register_pernet_device(&icmp_sk_ops);
+}
+
 EXPORT_SYMBOL(icmp_err_convert);
 EXPORT_SYMBOL(icmp_send);
 EXPORT_SYMBOL(icmp_statistics);