X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fkey%2Faf_key.c;h=ce980aa94ed8e45420223acaf9e1b25e4f03eb45;hb=f7f1b0f1e2fbadeab12d24236000e778aa9b1ead;hp=fdf75a1ba801019a4a7b46cd1629e63ff64c259d;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/net/key/af_key.c b/net/key/af_key.c index fdf75a1ba..ce980aa94 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -35,18 +35,24 @@ /* List of all pfkey sockets. */ -HLIST_HEAD(pfkey_table); +static HLIST_HEAD(pfkey_table); static DECLARE_WAIT_QUEUE_HEAD(pfkey_table_wait); -static rwlock_t pfkey_table_lock = RW_LOCK_UNLOCKED; +static DEFINE_RWLOCK(pfkey_table_lock); 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)> */ @@ -665,24 +665,26 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, sa->sadb_sa_state = SADB_SASTATE_DEAD; sa->sadb_sa_auth = 0; if (x->aalg) { - struct xfrm_algo_desc *a = xfrm_aalg_get_byname(x->aalg->alg_name); + struct xfrm_algo_desc *a = xfrm_aalg_get_byname(x->aalg->alg_name, 0); sa->sadb_sa_auth = a ? a->desc.sadb_alg_id : 0; } sa->sadb_sa_encrypt = 0; BUG_ON(x->ealg && x->calg); if (x->ealg) { - struct xfrm_algo_desc *a = xfrm_ealg_get_byname(x->ealg->alg_name); + struct xfrm_algo_desc *a = xfrm_ealg_get_byname(x->ealg->alg_name, 0); sa->sadb_sa_encrypt = a ? a->desc.sadb_alg_id : 0; } /* KAME compatible: sadb_sa_encrypt is overloaded with calg id */ if (x->calg) { - struct xfrm_algo_desc *a = xfrm_calg_get_byname(x->calg->alg_name); + struct xfrm_algo_desc *a = xfrm_calg_get_byname(x->calg->alg_name, 0); sa->sadb_sa_encrypt = a ? a->desc.sadb_alg_id : 0; } sa->sadb_sa_flags = 0; if (x->props.flags & XFRM_STATE_NOECN) sa->sadb_sa_flags |= SADB_SAFLAGS_NOECN; + if (x->props.flags & XFRM_STATE_DECAP_DSCP) + sa->sadb_sa_flags |= SADB_SAFLAGS_DECAP_DSCP; /* hard time */ if (hsc & 2) { @@ -965,6 +967,8 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, x->props.replay_window = sa->sadb_sa_replay; if (sa->sadb_sa_flags & SADB_SAFLAGS_NOECN) x->props.flags |= XFRM_STATE_NOECN; + if (sa->sadb_sa_flags & SADB_SAFLAGS_DECAP_DSCP) + x->props.flags |= XFRM_STATE_DECAP_DSCP; lifetime = (struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_HARD-1]; if (lifetime != NULL) { @@ -1075,15 +1079,6 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, n_type = ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1]; natt->encap_type = n_type->sadb_x_nat_t_type_type; - switch (natt->encap_type) { - case UDP_ENCAP_ESPINUDP: - case UDP_ENCAP_ESPINUDP_NON_IKE: - break; - default: - err = -ENOPROTOOPT; - goto out; - } - if (ext_hdrs[SADB_X_EXT_NAT_T_SPORT-1]) { struct sadb_x_nat_t_port* n_port = ext_hdrs[SADB_X_EXT_NAT_T_SPORT-1]; @@ -1165,7 +1160,16 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h break; #endif } - if (xdaddr) + + if (hdr->sadb_msg_seq) { + x = xfrm_find_acq_byseq(hdr->sadb_msg_seq); + if (x && xfrm_addr_cmp(&x->id.daddr, xdaddr, family)) { + xfrm_state_put(x); + x = NULL; + } + } + + if (!x) x = xfrm_find_acq(mode, reqid, proto, xdaddr, xsaddr, 1, family); if (x == NULL) @@ -1414,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) @@ -1510,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))) { @@ -2340,7 +2344,7 @@ static u32 get_acqseq(void) { u32 res; static u32 acqseq; - static spinlock_t acqseq_lock = SPIN_LOCK_UNLOCKED; + static DEFINE_SPINLOCK(acqseq_lock); spin_lock_bh(&acqseq_lock); res = (++acqseq ? : ++acqseq); @@ -2859,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);