vserver 2.0 rc7
[linux-2.6.git] / net / key / af_key.c
index c056494..ce980aa 100644 (file)
@@ -42,11 +42,17 @@ static atomic_t pfkey_table_users = ATOMIC_INIT(0);
 
 static atomic_t pfkey_socks_nr = ATOMIC_INIT(0);
 
-struct pfkey_opt {
-       int     registered;
-       int     promisc;
+struct pfkey_sock {
+       /* struct sock must be the first member of struct pfkey_sock */
+       struct sock     sk;
+       int             registered;
+       int             promisc;
 };
-#define pfkey_sk(__sk) ((struct pfkey_opt *)(__sk)->sk_protinfo)
+
+static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
+{
+       return (struct pfkey_sock *)sk;
+}
 
 static void pfkey_sock_destruct(struct sock *sk)
 {
@@ -60,8 +66,6 @@ static void pfkey_sock_destruct(struct sock *sk)
        BUG_TRAP(!atomic_read(&sk->sk_rmem_alloc));
        BUG_TRAP(!atomic_read(&sk->sk_wmem_alloc));
 
-       kfree(pfkey_sk(sk));
-
        atomic_dec(&pfkey_socks_nr);
 }
 
@@ -125,10 +129,15 @@ static void pfkey_remove(struct sock *sk)
        pfkey_table_ungrab();
 }
 
+static struct proto key_proto = {
+       .name     = "KEY",
+       .owner    = THIS_MODULE,
+       .obj_size = sizeof(struct pfkey_sock),
+};
+
 static int pfkey_create(struct socket *sock, int protocol)
 {
        struct sock *sk;
-       struct pfkey_opt *pfk;
        int err;
 
        if (!capable(CAP_NET_ADMIN))
@@ -139,21 +148,12 @@ static int pfkey_create(struct socket *sock, int protocol)
                return -EPROTONOSUPPORT;
 
        err = -ENOMEM;
-       sk = sk_alloc(PF_KEY, GFP_KERNEL, 1, NULL);
+       sk = sk_alloc(PF_KEY, GFP_KERNEL, &key_proto, 1);
        if (sk == NULL)
                goto out;
        
        sock->ops = &pfkey_ops;
        sock_init_data(sock, sk);
-       sk_set_owner(sk, THIS_MODULE);
-
-       err = -ENOMEM;
-       pfk = sk->sk_protinfo = kmalloc(sizeof(*pfk), GFP_KERNEL);
-       if (!pfk) {
-               sk_free(sk);
-               goto out;
-       }
-       memset(pfk, 0, sizeof(*pfk));
 
        sk->sk_family = PF_KEY;
        sk->sk_destruct = pfkey_sock_destruct;
@@ -233,7 +233,7 @@ static int pfkey_broadcast(struct sk_buff *skb, int allocation,
 
        pfkey_lock_table();
        sk_for_each(sk, node, &pfkey_table) {
-               struct pfkey_opt *pfk = pfkey_sk(sk);
+               struct pfkey_sock *pfk = pfkey_sk(sk);
                int err2;
 
                /* Yes, it means that if you are meant to receive this
@@ -598,7 +598,7 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys,
        /* address family check */
        sockaddr_size = pfkey_sockaddr_size(x->props.family);
        if (!sockaddr_size)
-               ERR_PTR(-EINVAL);
+               return ERR_PTR(-EINVAL);
 
        /* base, SA, (lifetime (HSC),) address(SD), (address(P),)
           key(AE), (identity(SD),) (sensitivity)> */
@@ -1418,7 +1418,7 @@ out_put_algs:
 
 static int pfkey_register(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
 {
-       struct pfkey_opt *pfk = pfkey_sk(sk);
+       struct pfkey_sock *pfk = pfkey_sk(sk);
        struct sk_buff *supp_skb;
 
        if (hdr->sadb_msg_satype > SADB_SATYPE_MAX)
@@ -1514,7 +1514,7 @@ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr
 
 static int pfkey_promisc(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
 {
-       struct pfkey_opt *pfk = pfkey_sk(sk);
+       struct pfkey_sock *pfk = pfkey_sk(sk);
        int satype = hdr->sadb_msg_satype;
 
        if (hdr->sadb_msg_len == (sizeof(*hdr) / sizeof(uint64_t))) {
@@ -2863,16 +2863,38 @@ static void __exit ipsec_pfkey_exit(void)
        xfrm_unregister_km(&pfkeyv2_mgr);
        remove_proc_entry("net/pfkey", NULL);
        sock_unregister(PF_KEY);
+       proto_unregister(&key_proto);
 }
 
 static int __init ipsec_pfkey_init(void)
 {
-       sock_register(&pfkey_family_ops);
+       int err = proto_register(&key_proto, 0);
+
+       if (err != 0)
+               goto out;
+
+       err = sock_register(&pfkey_family_ops);
+       if (err != 0)
+               goto out_unregister_key_proto;
 #ifdef CONFIG_PROC_FS
-       create_proc_read_entry("net/pfkey", 0, NULL, pfkey_read_proc, NULL);
+       err = -ENOMEM;
+       if (create_proc_read_entry("net/pfkey", 0, NULL, pfkey_read_proc, NULL) == NULL)
+               goto out_sock_unregister;
 #endif
-       xfrm_register_km(&pfkeyv2_mgr);
-       return 0;
+       err = xfrm_register_km(&pfkeyv2_mgr);
+       if (err != 0)
+               goto out_remove_proc_entry;
+out:
+       return err;
+out_remove_proc_entry:
+#ifdef CONFIG_PROC_FS
+       remove_proc_entry("net/pfkey", NULL);
+out_sock_unregister:
+#endif
+       sock_unregister(PF_KEY);
+out_unregister_key_proto:
+       proto_unregister(&key_proto);
+       goto out;
 }
 
 module_init(ipsec_pfkey_init);