Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / net / key / af_key.c
index bb78ef9..41dd2cb 100644 (file)
@@ -35,7 +35,7 @@
 #define _X2KEY(x) ((x) == XFRM_INF ? 0 : (x))
 #define _KEY2X(x) ((x) == 0 ? XFRM_INF : (x))
 
-static int pfkey_net_id;
+static int pfkey_net_id __read_mostly;
 struct netns_pfkey {
        /* List of all pfkey sockets. */
        struct hlist_head table;
@@ -177,7 +177,8 @@ static struct proto key_proto = {
        .obj_size = sizeof(struct pfkey_sock),
 };
 
-static int pfkey_create(struct net *net, struct socket *sock, int protocol)
+static int pfkey_create(struct net *net, struct socket *sock, int protocol,
+                       int kern)
 {
        struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
        struct sock *sk;
@@ -313,8 +314,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
        if (one_sk != NULL)
                err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk);
 
-       if (skb2)
-               kfree_skb(skb2);
+       kfree_skb(skb2);
        kfree_skb(skb);
        return err;
 }
@@ -1193,6 +1193,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
                        x->aalg->alg_key_len = key->sadb_key_bits;
                        memcpy(x->aalg->alg_key, key+1, keysize);
                }
+               x->aalg->alg_trunc_len = a->uinfo.auth.icv_truncbits;
                x->props.aalgo = sa->sadb_sa_auth;
                /* x->algo.flags = sa->sadb_sa_flags; */
        }
@@ -1285,6 +1286,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
                                ext_hdrs[SADB_X_EXT_NAT_T_DPORT-1];
                        natt->encap_dport = n_port->sadb_x_nat_t_port_port;
                }
+               memset(&natt->encap_oa, 0, sizeof(natt->encap_oa));
        }
 
        err = xfrm_init_state(x);
@@ -3017,12 +3019,11 @@ static int pfkey_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_e
 static u32 get_acqseq(void)
 {
        u32 res;
-       static u32 acqseq;
-       static DEFINE_SPINLOCK(acqseq_lock);
+       static atomic_t acqseq;
 
-       spin_lock_bh(&acqseq_lock);
-       res = (++acqseq ? : ++acqseq);
-       spin_unlock_bh(&acqseq_lock);
+       do {
+               res = atomic_inc_return(&acqseq);
+       } while (!res);
        return res;
 }
 
@@ -3572,8 +3573,7 @@ static int pfkey_sendmsg(struct kiocb *kiocb,
 out:
        if (err && hdr && pfkey_error(hdr, err, sk) == 0)
                err = 0;
-       if (skb)
-               kfree_skb(skb);
+       kfree_skb(skb);
 
        return err ? : len;
 }
@@ -3607,7 +3607,7 @@ static int pfkey_recvmsg(struct kiocb *kiocb,
        if (err)
                goto out_free;
 
-       sock_recv_timestamp(msg, sk, skb);
+       sock_recv_ts_and_drops(msg, sk, skb);
 
        err = (flags & MSG_TRUNC) ? skb->len : copied;
 
@@ -3645,7 +3645,7 @@ static const struct proto_ops pfkey_ops = {
        .recvmsg        =       pfkey_recvmsg,
 };
 
-static struct net_proto_family pfkey_family_ops = {
+static const struct net_proto_family pfkey_family_ops = {
        .family =       PF_KEY,
        .create =       pfkey_create,
        .owner  =       THIS_MODULE,
@@ -3663,8 +3663,8 @@ static int pfkey_seq_show(struct seq_file *f, void *v)
                seq_printf(f ,"%p %-6d %-6u %-6u %-6u %-6lu\n",
                               s,
                               atomic_read(&s->sk_refcnt),
-                              atomic_read(&s->sk_rmem_alloc),
-                              atomic_read(&s->sk_wmem_alloc),
+                              sk_rmem_alloc_get(s),
+                              sk_wmem_alloc_get(s),
                               sock_i_uid(s),
                               sock_i_ino(s)
                               );
@@ -3673,7 +3673,7 @@ static int pfkey_seq_show(struct seq_file *f, void *v)
 
 static void *pfkey_seq_start(struct seq_file *f, loff_t *ppos)
 {
-       struct net *net = &init_net;
+       struct net *net = seq_file_net(f);
        struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
        struct sock *s;
        struct hlist_node *node;
@@ -3692,7 +3692,7 @@ static void *pfkey_seq_start(struct seq_file *f, loff_t *ppos)
 
 static void *pfkey_seq_next(struct seq_file *f, void *v, loff_t *ppos)
 {
-       struct net *net = &init_net;
+       struct net *net = seq_file_net(f);
        struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
 
        ++*ppos;
@@ -3706,7 +3706,7 @@ static void pfkey_seq_stop(struct seq_file *f, void *v)
        read_unlock(&pfkey_table_lock);
 }
 
-static struct seq_operations pfkey_seq_ops = {
+static const struct seq_operations pfkey_seq_ops = {
        .start  = pfkey_seq_start,
        .next   = pfkey_seq_next,
        .stop   = pfkey_seq_stop,
@@ -3715,38 +3715,39 @@ static struct seq_operations pfkey_seq_ops = {
 
 static int pfkey_seq_open(struct inode *inode, struct file *file)
 {
-       return seq_open(file, &pfkey_seq_ops);
+       return seq_open_net(inode, file, &pfkey_seq_ops,
+                           sizeof(struct seq_net_private));
 }
 
-static struct file_operations pfkey_proc_ops = {
+static const struct file_operations pfkey_proc_ops = {
        .open    = pfkey_seq_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = seq_release,
+       .release = seq_release_net,
 };
 
-static int pfkey_init_proc(void)
+static int __net_init pfkey_init_proc(struct net *net)
 {
        struct proc_dir_entry *e;
 
-       e = proc_net_fops_create(&init_net, "pfkey", 0, &pfkey_proc_ops);
+       e = proc_net_fops_create(net, "pfkey", 0, &pfkey_proc_ops);
        if (e == NULL)
                return -ENOMEM;
 
        return 0;
 }
 
-static void pfkey_exit_proc(void)
+static void __net_exit pfkey_exit_proc(struct net *net)
 {
-       proc_net_remove(&init_net, "pfkey");
+       proc_net_remove(net, "pfkey");
 }
 #else
-static inline int pfkey_init_proc(void)
+static inline int pfkey_init_proc(struct net *net)
 {
        return 0;
 }
 
-static inline void pfkey_exit_proc(void)
+static inline void pfkey_exit_proc(struct net *net)
 {
 }
 #endif
@@ -3764,24 +3765,14 @@ static struct xfrm_mgr pfkeyv2_mgr =
 
 static int __net_init pfkey_net_init(struct net *net)
 {
-       struct netns_pfkey *net_pfkey;
+       struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
        int rv;
 
-       net_pfkey = kmalloc(sizeof(struct netns_pfkey), GFP_KERNEL);
-       if (!net_pfkey) {
-               rv = -ENOMEM;
-               goto out_kmalloc;
-       }
        INIT_HLIST_HEAD(&net_pfkey->table);
        atomic_set(&net_pfkey->socks_nr, 0);
-       rv = net_assign_generic(net, pfkey_net_id, net_pfkey);
-       if (rv < 0)
-               goto out_assign;
-       return 0;
 
-out_assign:
-       kfree(net_pfkey);
-out_kmalloc:
+       rv = pfkey_init_proc(net);
+
        return rv;
 }
 
@@ -3789,21 +3780,22 @@ static void __net_exit pfkey_net_exit(struct net *net)
 {
        struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
 
+       pfkey_exit_proc(net);
        BUG_ON(!hlist_empty(&net_pfkey->table));
-       kfree(net_pfkey);
 }
 
 static struct pernet_operations pfkey_net_ops = {
        .init = pfkey_net_init,
        .exit = pfkey_net_exit,
+       .id   = &pfkey_net_id,
+       .size = sizeof(struct netns_pfkey),
 };
 
 static void __exit ipsec_pfkey_exit(void)
 {
-       unregister_pernet_gen_subsys(pfkey_net_id, &pfkey_net_ops);
        xfrm_unregister_km(&pfkeyv2_mgr);
-       pfkey_exit_proc();
        sock_unregister(PF_KEY);
+       unregister_pernet_subsys(&pfkey_net_ops);
        proto_unregister(&key_proto);
 }
 
@@ -3814,26 +3806,22 @@ static int __init ipsec_pfkey_init(void)
        if (err != 0)
                goto out;
 
-       err = sock_register(&pfkey_family_ops);
+       err = register_pernet_subsys(&pfkey_net_ops);
        if (err != 0)
                goto out_unregister_key_proto;
-       err = pfkey_init_proc();
+       err = sock_register(&pfkey_family_ops);
        if (err != 0)
-               goto out_sock_unregister;
+               goto out_unregister_pernet;
        err = xfrm_register_km(&pfkeyv2_mgr);
        if (err != 0)
-               goto out_remove_proc_entry;
-       err = register_pernet_gen_subsys(&pfkey_net_id, &pfkey_net_ops);
-       if (err != 0)
-               goto out_xfrm_unregister_km;
+               goto out_sock_unregister;
 out:
        return err;
-out_xfrm_unregister_km:
-       xfrm_unregister_km(&pfkeyv2_mgr);
-out_remove_proc_entry:
-       pfkey_exit_proc();
+
 out_sock_unregister:
        sock_unregister(PF_KEY);
+out_unregister_pernet:
+       unregister_pernet_subsys(&pfkey_net_ops);
 out_unregister_key_proto:
        proto_unregister(&key_proto);
        goto out;