xref: /OK3568_Linux_fs/kernel/net/key/af_key.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * net/key/af_key.c	An implementation of PF_KEYv2 sockets.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Authors:	Maxim Giryaev	<gem@asplinux.ru>
6*4882a593Smuzhiyun  *		David S. Miller	<davem@redhat.com>
7*4882a593Smuzhiyun  *		Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
8*4882a593Smuzhiyun  *		Kunihiro Ishiguro <kunihiro@ipinfusion.com>
9*4882a593Smuzhiyun  *		Kazunori MIYAZAWA / USAGI Project <miyazawa@linux-ipv6.org>
10*4882a593Smuzhiyun  *		Derek Atkins <derek@ihtfp.com>
11*4882a593Smuzhiyun  */
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include <linux/capability.h>
14*4882a593Smuzhiyun #include <linux/module.h>
15*4882a593Smuzhiyun #include <linux/kernel.h>
16*4882a593Smuzhiyun #include <linux/socket.h>
17*4882a593Smuzhiyun #include <linux/pfkeyv2.h>
18*4882a593Smuzhiyun #include <linux/ipsec.h>
19*4882a593Smuzhiyun #include <linux/skbuff.h>
20*4882a593Smuzhiyun #include <linux/rtnetlink.h>
21*4882a593Smuzhiyun #include <linux/in.h>
22*4882a593Smuzhiyun #include <linux/in6.h>
23*4882a593Smuzhiyun #include <linux/proc_fs.h>
24*4882a593Smuzhiyun #include <linux/init.h>
25*4882a593Smuzhiyun #include <linux/slab.h>
26*4882a593Smuzhiyun #include <net/net_namespace.h>
27*4882a593Smuzhiyun #include <net/netns/generic.h>
28*4882a593Smuzhiyun #include <net/xfrm.h>
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #include <net/sock.h>
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun #define _X2KEY(x) ((x) == XFRM_INF ? 0 : (x))
33*4882a593Smuzhiyun #define _KEY2X(x) ((x) == 0 ? XFRM_INF : (x))
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun static unsigned int pfkey_net_id __read_mostly;
36*4882a593Smuzhiyun struct netns_pfkey {
37*4882a593Smuzhiyun 	/* List of all pfkey sockets. */
38*4882a593Smuzhiyun 	struct hlist_head table;
39*4882a593Smuzhiyun 	atomic_t socks_nr;
40*4882a593Smuzhiyun };
41*4882a593Smuzhiyun static DEFINE_MUTEX(pfkey_mutex);
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun #define DUMMY_MARK 0
44*4882a593Smuzhiyun static const struct xfrm_mark dummy_mark = {0, 0};
45*4882a593Smuzhiyun struct pfkey_sock {
46*4882a593Smuzhiyun 	/* struct sock must be the first member of struct pfkey_sock */
47*4882a593Smuzhiyun 	struct sock	sk;
48*4882a593Smuzhiyun 	int		registered;
49*4882a593Smuzhiyun 	int		promisc;
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	struct {
52*4882a593Smuzhiyun 		uint8_t		msg_version;
53*4882a593Smuzhiyun 		uint32_t	msg_portid;
54*4882a593Smuzhiyun 		int		(*dump)(struct pfkey_sock *sk);
55*4882a593Smuzhiyun 		void		(*done)(struct pfkey_sock *sk);
56*4882a593Smuzhiyun 		union {
57*4882a593Smuzhiyun 			struct xfrm_policy_walk	policy;
58*4882a593Smuzhiyun 			struct xfrm_state_walk	state;
59*4882a593Smuzhiyun 		} u;
60*4882a593Smuzhiyun 		struct sk_buff	*skb;
61*4882a593Smuzhiyun 	} dump;
62*4882a593Smuzhiyun 	struct mutex dump_lock;
63*4882a593Smuzhiyun };
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len,
66*4882a593Smuzhiyun 			       xfrm_address_t *saddr, xfrm_address_t *daddr,
67*4882a593Smuzhiyun 			       u16 *family);
68*4882a593Smuzhiyun 
pfkey_sk(struct sock * sk)69*4882a593Smuzhiyun static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun 	return (struct pfkey_sock *)sk;
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun 
pfkey_can_dump(const struct sock * sk)74*4882a593Smuzhiyun static int pfkey_can_dump(const struct sock *sk)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun 	if (3 * atomic_read(&sk->sk_rmem_alloc) <= 2 * sk->sk_rcvbuf)
77*4882a593Smuzhiyun 		return 1;
78*4882a593Smuzhiyun 	return 0;
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun 
pfkey_terminate_dump(struct pfkey_sock * pfk)81*4882a593Smuzhiyun static void pfkey_terminate_dump(struct pfkey_sock *pfk)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun 	if (pfk->dump.dump) {
84*4882a593Smuzhiyun 		if (pfk->dump.skb) {
85*4882a593Smuzhiyun 			kfree_skb(pfk->dump.skb);
86*4882a593Smuzhiyun 			pfk->dump.skb = NULL;
87*4882a593Smuzhiyun 		}
88*4882a593Smuzhiyun 		pfk->dump.done(pfk);
89*4882a593Smuzhiyun 		pfk->dump.dump = NULL;
90*4882a593Smuzhiyun 		pfk->dump.done = NULL;
91*4882a593Smuzhiyun 	}
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
pfkey_sock_destruct(struct sock * sk)94*4882a593Smuzhiyun static void pfkey_sock_destruct(struct sock *sk)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	struct net *net = sock_net(sk);
97*4882a593Smuzhiyun 	struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	pfkey_terminate_dump(pfkey_sk(sk));
100*4882a593Smuzhiyun 	skb_queue_purge(&sk->sk_receive_queue);
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	if (!sock_flag(sk, SOCK_DEAD)) {
103*4882a593Smuzhiyun 		pr_err("Attempt to release alive pfkey socket: %p\n", sk);
104*4882a593Smuzhiyun 		return;
105*4882a593Smuzhiyun 	}
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	WARN_ON(atomic_read(&sk->sk_rmem_alloc));
108*4882a593Smuzhiyun 	WARN_ON(refcount_read(&sk->sk_wmem_alloc));
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	atomic_dec(&net_pfkey->socks_nr);
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun static const struct proto_ops pfkey_ops;
114*4882a593Smuzhiyun 
pfkey_insert(struct sock * sk)115*4882a593Smuzhiyun static void pfkey_insert(struct sock *sk)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun 	struct net *net = sock_net(sk);
118*4882a593Smuzhiyun 	struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	mutex_lock(&pfkey_mutex);
121*4882a593Smuzhiyun 	sk_add_node_rcu(sk, &net_pfkey->table);
122*4882a593Smuzhiyun 	mutex_unlock(&pfkey_mutex);
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun 
pfkey_remove(struct sock * sk)125*4882a593Smuzhiyun static void pfkey_remove(struct sock *sk)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun 	mutex_lock(&pfkey_mutex);
128*4882a593Smuzhiyun 	sk_del_node_init_rcu(sk);
129*4882a593Smuzhiyun 	mutex_unlock(&pfkey_mutex);
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun static struct proto key_proto = {
133*4882a593Smuzhiyun 	.name	  = "KEY",
134*4882a593Smuzhiyun 	.owner	  = THIS_MODULE,
135*4882a593Smuzhiyun 	.obj_size = sizeof(struct pfkey_sock),
136*4882a593Smuzhiyun };
137*4882a593Smuzhiyun 
pfkey_create(struct net * net,struct socket * sock,int protocol,int kern)138*4882a593Smuzhiyun static int pfkey_create(struct net *net, struct socket *sock, int protocol,
139*4882a593Smuzhiyun 			int kern)
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun 	struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
142*4882a593Smuzhiyun 	struct sock *sk;
143*4882a593Smuzhiyun 	struct pfkey_sock *pfk;
144*4882a593Smuzhiyun 	int err;
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
147*4882a593Smuzhiyun 		return -EPERM;
148*4882a593Smuzhiyun 	if (sock->type != SOCK_RAW)
149*4882a593Smuzhiyun 		return -ESOCKTNOSUPPORT;
150*4882a593Smuzhiyun 	if (protocol != PF_KEY_V2)
151*4882a593Smuzhiyun 		return -EPROTONOSUPPORT;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	err = -ENOMEM;
154*4882a593Smuzhiyun 	sk = sk_alloc(net, PF_KEY, GFP_KERNEL, &key_proto, kern);
155*4882a593Smuzhiyun 	if (sk == NULL)
156*4882a593Smuzhiyun 		goto out;
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	pfk = pfkey_sk(sk);
159*4882a593Smuzhiyun 	mutex_init(&pfk->dump_lock);
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	sock->ops = &pfkey_ops;
162*4882a593Smuzhiyun 	sock_init_data(sock, sk);
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	sk->sk_family = PF_KEY;
165*4882a593Smuzhiyun 	sk->sk_destruct = pfkey_sock_destruct;
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	atomic_inc(&net_pfkey->socks_nr);
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	pfkey_insert(sk);
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	return 0;
172*4882a593Smuzhiyun out:
173*4882a593Smuzhiyun 	return err;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun 
pfkey_release(struct socket * sock)176*4882a593Smuzhiyun static int pfkey_release(struct socket *sock)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun 	struct sock *sk = sock->sk;
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	if (!sk)
181*4882a593Smuzhiyun 		return 0;
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	pfkey_remove(sk);
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	sock_orphan(sk);
186*4882a593Smuzhiyun 	sock->sk = NULL;
187*4882a593Smuzhiyun 	skb_queue_purge(&sk->sk_write_queue);
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	synchronize_rcu();
190*4882a593Smuzhiyun 	sock_put(sk);
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	return 0;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun 
pfkey_broadcast_one(struct sk_buff * skb,gfp_t allocation,struct sock * sk)195*4882a593Smuzhiyun static int pfkey_broadcast_one(struct sk_buff *skb, gfp_t allocation,
196*4882a593Smuzhiyun 			       struct sock *sk)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun 	int err = -ENOBUFS;
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf)
201*4882a593Smuzhiyun 		return err;
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	skb = skb_clone(skb, allocation);
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	if (skb) {
206*4882a593Smuzhiyun 		skb_set_owner_r(skb, sk);
207*4882a593Smuzhiyun 		skb_queue_tail(&sk->sk_receive_queue, skb);
208*4882a593Smuzhiyun 		sk->sk_data_ready(sk);
209*4882a593Smuzhiyun 		err = 0;
210*4882a593Smuzhiyun 	}
211*4882a593Smuzhiyun 	return err;
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun /* Send SKB to all pfkey sockets matching selected criteria.  */
215*4882a593Smuzhiyun #define BROADCAST_ALL		0
216*4882a593Smuzhiyun #define BROADCAST_ONE		1
217*4882a593Smuzhiyun #define BROADCAST_REGISTERED	2
218*4882a593Smuzhiyun #define BROADCAST_PROMISC_ONLY	4
pfkey_broadcast(struct sk_buff * skb,gfp_t allocation,int broadcast_flags,struct sock * one_sk,struct net * net)219*4882a593Smuzhiyun static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
220*4882a593Smuzhiyun 			   int broadcast_flags, struct sock *one_sk,
221*4882a593Smuzhiyun 			   struct net *net)
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun 	struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
224*4882a593Smuzhiyun 	struct sock *sk;
225*4882a593Smuzhiyun 	int err = -ESRCH;
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	/* XXX Do we need something like netlink_overrun?  I think
228*4882a593Smuzhiyun 	 * XXX PF_KEY socket apps will not mind current behavior.
229*4882a593Smuzhiyun 	 */
230*4882a593Smuzhiyun 	if (!skb)
231*4882a593Smuzhiyun 		return -ENOMEM;
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	rcu_read_lock();
234*4882a593Smuzhiyun 	sk_for_each_rcu(sk, &net_pfkey->table) {
235*4882a593Smuzhiyun 		struct pfkey_sock *pfk = pfkey_sk(sk);
236*4882a593Smuzhiyun 		int err2;
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 		/* Yes, it means that if you are meant to receive this
239*4882a593Smuzhiyun 		 * pfkey message you receive it twice as promiscuous
240*4882a593Smuzhiyun 		 * socket.
241*4882a593Smuzhiyun 		 */
242*4882a593Smuzhiyun 		if (pfk->promisc)
243*4882a593Smuzhiyun 			pfkey_broadcast_one(skb, GFP_ATOMIC, sk);
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 		/* the exact target will be processed later */
246*4882a593Smuzhiyun 		if (sk == one_sk)
247*4882a593Smuzhiyun 			continue;
248*4882a593Smuzhiyun 		if (broadcast_flags != BROADCAST_ALL) {
249*4882a593Smuzhiyun 			if (broadcast_flags & BROADCAST_PROMISC_ONLY)
250*4882a593Smuzhiyun 				continue;
251*4882a593Smuzhiyun 			if ((broadcast_flags & BROADCAST_REGISTERED) &&
252*4882a593Smuzhiyun 			    !pfk->registered)
253*4882a593Smuzhiyun 				continue;
254*4882a593Smuzhiyun 			if (broadcast_flags & BROADCAST_ONE)
255*4882a593Smuzhiyun 				continue;
256*4882a593Smuzhiyun 		}
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 		err2 = pfkey_broadcast_one(skb, GFP_ATOMIC, sk);
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 		/* Error is cleared after successful sending to at least one
261*4882a593Smuzhiyun 		 * registered KM */
262*4882a593Smuzhiyun 		if ((broadcast_flags & BROADCAST_REGISTERED) && err)
263*4882a593Smuzhiyun 			err = err2;
264*4882a593Smuzhiyun 	}
265*4882a593Smuzhiyun 	rcu_read_unlock();
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	if (one_sk != NULL)
268*4882a593Smuzhiyun 		err = pfkey_broadcast_one(skb, allocation, one_sk);
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	kfree_skb(skb);
271*4882a593Smuzhiyun 	return err;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun 
pfkey_do_dump(struct pfkey_sock * pfk)274*4882a593Smuzhiyun static int pfkey_do_dump(struct pfkey_sock *pfk)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun 	struct sadb_msg *hdr;
277*4882a593Smuzhiyun 	int rc;
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	mutex_lock(&pfk->dump_lock);
280*4882a593Smuzhiyun 	if (!pfk->dump.dump) {
281*4882a593Smuzhiyun 		rc = 0;
282*4882a593Smuzhiyun 		goto out;
283*4882a593Smuzhiyun 	}
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	rc = pfk->dump.dump(pfk);
286*4882a593Smuzhiyun 	if (rc == -ENOBUFS) {
287*4882a593Smuzhiyun 		rc = 0;
288*4882a593Smuzhiyun 		goto out;
289*4882a593Smuzhiyun 	}
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	if (pfk->dump.skb) {
292*4882a593Smuzhiyun 		if (!pfkey_can_dump(&pfk->sk)) {
293*4882a593Smuzhiyun 			rc = 0;
294*4882a593Smuzhiyun 			goto out;
295*4882a593Smuzhiyun 		}
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 		hdr = (struct sadb_msg *) pfk->dump.skb->data;
298*4882a593Smuzhiyun 		hdr->sadb_msg_seq = 0;
299*4882a593Smuzhiyun 		hdr->sadb_msg_errno = rc;
300*4882a593Smuzhiyun 		pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
301*4882a593Smuzhiyun 				&pfk->sk, sock_net(&pfk->sk));
302*4882a593Smuzhiyun 		pfk->dump.skb = NULL;
303*4882a593Smuzhiyun 	}
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	pfkey_terminate_dump(pfk);
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun out:
308*4882a593Smuzhiyun 	mutex_unlock(&pfk->dump_lock);
309*4882a593Smuzhiyun 	return rc;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun 
pfkey_hdr_dup(struct sadb_msg * new,const struct sadb_msg * orig)312*4882a593Smuzhiyun static inline void pfkey_hdr_dup(struct sadb_msg *new,
313*4882a593Smuzhiyun 				 const struct sadb_msg *orig)
314*4882a593Smuzhiyun {
315*4882a593Smuzhiyun 	*new = *orig;
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun 
pfkey_error(const struct sadb_msg * orig,int err,struct sock * sk)318*4882a593Smuzhiyun static int pfkey_error(const struct sadb_msg *orig, int err, struct sock *sk)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun 	struct sk_buff *skb = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_KERNEL);
321*4882a593Smuzhiyun 	struct sadb_msg *hdr;
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 	if (!skb)
324*4882a593Smuzhiyun 		return -ENOBUFS;
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	/* Woe be to the platform trying to support PFKEY yet
327*4882a593Smuzhiyun 	 * having normal errnos outside the 1-255 range, inclusive.
328*4882a593Smuzhiyun 	 */
329*4882a593Smuzhiyun 	err = -err;
330*4882a593Smuzhiyun 	if (err == ERESTARTSYS ||
331*4882a593Smuzhiyun 	    err == ERESTARTNOHAND ||
332*4882a593Smuzhiyun 	    err == ERESTARTNOINTR)
333*4882a593Smuzhiyun 		err = EINTR;
334*4882a593Smuzhiyun 	if (err >= 512)
335*4882a593Smuzhiyun 		err = EINVAL;
336*4882a593Smuzhiyun 	BUG_ON(err <= 0 || err >= 256);
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	hdr = skb_put(skb, sizeof(struct sadb_msg));
339*4882a593Smuzhiyun 	pfkey_hdr_dup(hdr, orig);
340*4882a593Smuzhiyun 	hdr->sadb_msg_errno = (uint8_t) err;
341*4882a593Smuzhiyun 	hdr->sadb_msg_len = (sizeof(struct sadb_msg) /
342*4882a593Smuzhiyun 			     sizeof(uint64_t));
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 	pfkey_broadcast(skb, GFP_KERNEL, BROADCAST_ONE, sk, sock_net(sk));
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 	return 0;
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun static const u8 sadb_ext_min_len[] = {
350*4882a593Smuzhiyun 	[SADB_EXT_RESERVED]		= (u8) 0,
351*4882a593Smuzhiyun 	[SADB_EXT_SA]			= (u8) sizeof(struct sadb_sa),
352*4882a593Smuzhiyun 	[SADB_EXT_LIFETIME_CURRENT]	= (u8) sizeof(struct sadb_lifetime),
353*4882a593Smuzhiyun 	[SADB_EXT_LIFETIME_HARD]	= (u8) sizeof(struct sadb_lifetime),
354*4882a593Smuzhiyun 	[SADB_EXT_LIFETIME_SOFT]	= (u8) sizeof(struct sadb_lifetime),
355*4882a593Smuzhiyun 	[SADB_EXT_ADDRESS_SRC]		= (u8) sizeof(struct sadb_address),
356*4882a593Smuzhiyun 	[SADB_EXT_ADDRESS_DST]		= (u8) sizeof(struct sadb_address),
357*4882a593Smuzhiyun 	[SADB_EXT_ADDRESS_PROXY]	= (u8) sizeof(struct sadb_address),
358*4882a593Smuzhiyun 	[SADB_EXT_KEY_AUTH]		= (u8) sizeof(struct sadb_key),
359*4882a593Smuzhiyun 	[SADB_EXT_KEY_ENCRYPT]		= (u8) sizeof(struct sadb_key),
360*4882a593Smuzhiyun 	[SADB_EXT_IDENTITY_SRC]		= (u8) sizeof(struct sadb_ident),
361*4882a593Smuzhiyun 	[SADB_EXT_IDENTITY_DST]		= (u8) sizeof(struct sadb_ident),
362*4882a593Smuzhiyun 	[SADB_EXT_SENSITIVITY]		= (u8) sizeof(struct sadb_sens),
363*4882a593Smuzhiyun 	[SADB_EXT_PROPOSAL]		= (u8) sizeof(struct sadb_prop),
364*4882a593Smuzhiyun 	[SADB_EXT_SUPPORTED_AUTH]	= (u8) sizeof(struct sadb_supported),
365*4882a593Smuzhiyun 	[SADB_EXT_SUPPORTED_ENCRYPT]	= (u8) sizeof(struct sadb_supported),
366*4882a593Smuzhiyun 	[SADB_EXT_SPIRANGE]		= (u8) sizeof(struct sadb_spirange),
367*4882a593Smuzhiyun 	[SADB_X_EXT_KMPRIVATE]		= (u8) sizeof(struct sadb_x_kmprivate),
368*4882a593Smuzhiyun 	[SADB_X_EXT_POLICY]		= (u8) sizeof(struct sadb_x_policy),
369*4882a593Smuzhiyun 	[SADB_X_EXT_SA2]		= (u8) sizeof(struct sadb_x_sa2),
370*4882a593Smuzhiyun 	[SADB_X_EXT_NAT_T_TYPE]		= (u8) sizeof(struct sadb_x_nat_t_type),
371*4882a593Smuzhiyun 	[SADB_X_EXT_NAT_T_SPORT]	= (u8) sizeof(struct sadb_x_nat_t_port),
372*4882a593Smuzhiyun 	[SADB_X_EXT_NAT_T_DPORT]	= (u8) sizeof(struct sadb_x_nat_t_port),
373*4882a593Smuzhiyun 	[SADB_X_EXT_NAT_T_OA]		= (u8) sizeof(struct sadb_address),
374*4882a593Smuzhiyun 	[SADB_X_EXT_SEC_CTX]		= (u8) sizeof(struct sadb_x_sec_ctx),
375*4882a593Smuzhiyun 	[SADB_X_EXT_KMADDRESS]		= (u8) sizeof(struct sadb_x_kmaddress),
376*4882a593Smuzhiyun 	[SADB_X_EXT_FILTER]		= (u8) sizeof(struct sadb_x_filter),
377*4882a593Smuzhiyun };
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun /* Verify sadb_address_{len,prefixlen} against sa_family.  */
verify_address_len(const void * p)380*4882a593Smuzhiyun static int verify_address_len(const void *p)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun 	const struct sadb_address *sp = p;
383*4882a593Smuzhiyun 	const struct sockaddr *addr = (const struct sockaddr *)(sp + 1);
384*4882a593Smuzhiyun 	const struct sockaddr_in *sin;
385*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
386*4882a593Smuzhiyun 	const struct sockaddr_in6 *sin6;
387*4882a593Smuzhiyun #endif
388*4882a593Smuzhiyun 	int len;
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 	if (sp->sadb_address_len <
391*4882a593Smuzhiyun 	    DIV_ROUND_UP(sizeof(*sp) + offsetofend(typeof(*addr), sa_family),
392*4882a593Smuzhiyun 			 sizeof(uint64_t)))
393*4882a593Smuzhiyun 		return -EINVAL;
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun 	switch (addr->sa_family) {
396*4882a593Smuzhiyun 	case AF_INET:
397*4882a593Smuzhiyun 		len = DIV_ROUND_UP(sizeof(*sp) + sizeof(*sin), sizeof(uint64_t));
398*4882a593Smuzhiyun 		if (sp->sadb_address_len != len ||
399*4882a593Smuzhiyun 		    sp->sadb_address_prefixlen > 32)
400*4882a593Smuzhiyun 			return -EINVAL;
401*4882a593Smuzhiyun 		break;
402*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
403*4882a593Smuzhiyun 	case AF_INET6:
404*4882a593Smuzhiyun 		len = DIV_ROUND_UP(sizeof(*sp) + sizeof(*sin6), sizeof(uint64_t));
405*4882a593Smuzhiyun 		if (sp->sadb_address_len != len ||
406*4882a593Smuzhiyun 		    sp->sadb_address_prefixlen > 128)
407*4882a593Smuzhiyun 			return -EINVAL;
408*4882a593Smuzhiyun 		break;
409*4882a593Smuzhiyun #endif
410*4882a593Smuzhiyun 	default:
411*4882a593Smuzhiyun 		/* It is user using kernel to keep track of security
412*4882a593Smuzhiyun 		 * associations for another protocol, such as
413*4882a593Smuzhiyun 		 * OSPF/RSVP/RIPV2/MIP.  It is user's job to verify
414*4882a593Smuzhiyun 		 * lengths.
415*4882a593Smuzhiyun 		 *
416*4882a593Smuzhiyun 		 * XXX Actually, association/policy database is not yet
417*4882a593Smuzhiyun 		 * XXX able to cope with arbitrary sockaddr families.
418*4882a593Smuzhiyun 		 * XXX When it can, remove this -EINVAL.  -DaveM
419*4882a593Smuzhiyun 		 */
420*4882a593Smuzhiyun 		return -EINVAL;
421*4882a593Smuzhiyun 	}
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	return 0;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun 
sadb_key_len(const struct sadb_key * key)426*4882a593Smuzhiyun static inline int sadb_key_len(const struct sadb_key *key)
427*4882a593Smuzhiyun {
428*4882a593Smuzhiyun 	int key_bytes = DIV_ROUND_UP(key->sadb_key_bits, 8);
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 	return DIV_ROUND_UP(sizeof(struct sadb_key) + key_bytes,
431*4882a593Smuzhiyun 			    sizeof(uint64_t));
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun 
verify_key_len(const void * p)434*4882a593Smuzhiyun static int verify_key_len(const void *p)
435*4882a593Smuzhiyun {
436*4882a593Smuzhiyun 	const struct sadb_key *key = p;
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 	if (sadb_key_len(key) > key->sadb_key_len)
439*4882a593Smuzhiyun 		return -EINVAL;
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 	return 0;
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun 
pfkey_sec_ctx_len(const struct sadb_x_sec_ctx * sec_ctx)444*4882a593Smuzhiyun static inline int pfkey_sec_ctx_len(const struct sadb_x_sec_ctx *sec_ctx)
445*4882a593Smuzhiyun {
446*4882a593Smuzhiyun 	return DIV_ROUND_UP(sizeof(struct sadb_x_sec_ctx) +
447*4882a593Smuzhiyun 			    sec_ctx->sadb_x_ctx_len,
448*4882a593Smuzhiyun 			    sizeof(uint64_t));
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun 
verify_sec_ctx_len(const void * p)451*4882a593Smuzhiyun static inline int verify_sec_ctx_len(const void *p)
452*4882a593Smuzhiyun {
453*4882a593Smuzhiyun 	const struct sadb_x_sec_ctx *sec_ctx = p;
454*4882a593Smuzhiyun 	int len = sec_ctx->sadb_x_ctx_len;
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun 	if (len > PAGE_SIZE)
457*4882a593Smuzhiyun 		return -EINVAL;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 	len = pfkey_sec_ctx_len(sec_ctx);
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 	if (sec_ctx->sadb_x_sec_len != len)
462*4882a593Smuzhiyun 		return -EINVAL;
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	return 0;
465*4882a593Smuzhiyun }
466*4882a593Smuzhiyun 
pfkey_sadb2xfrm_user_sec_ctx(const struct sadb_x_sec_ctx * sec_ctx,gfp_t gfp)467*4882a593Smuzhiyun static inline struct xfrm_user_sec_ctx *pfkey_sadb2xfrm_user_sec_ctx(const struct sadb_x_sec_ctx *sec_ctx,
468*4882a593Smuzhiyun 								     gfp_t gfp)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun 	struct xfrm_user_sec_ctx *uctx = NULL;
471*4882a593Smuzhiyun 	int ctx_size = sec_ctx->sadb_x_ctx_len;
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun 	uctx = kmalloc((sizeof(*uctx)+ctx_size), gfp);
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	if (!uctx)
476*4882a593Smuzhiyun 		return NULL;
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 	uctx->len = pfkey_sec_ctx_len(sec_ctx);
479*4882a593Smuzhiyun 	uctx->exttype = sec_ctx->sadb_x_sec_exttype;
480*4882a593Smuzhiyun 	uctx->ctx_doi = sec_ctx->sadb_x_ctx_doi;
481*4882a593Smuzhiyun 	uctx->ctx_alg = sec_ctx->sadb_x_ctx_alg;
482*4882a593Smuzhiyun 	uctx->ctx_len = sec_ctx->sadb_x_ctx_len;
483*4882a593Smuzhiyun 	memcpy(uctx + 1, sec_ctx + 1,
484*4882a593Smuzhiyun 	       uctx->ctx_len);
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun 	return uctx;
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun 
present_and_same_family(const struct sadb_address * src,const struct sadb_address * dst)489*4882a593Smuzhiyun static int present_and_same_family(const struct sadb_address *src,
490*4882a593Smuzhiyun 				   const struct sadb_address *dst)
491*4882a593Smuzhiyun {
492*4882a593Smuzhiyun 	const struct sockaddr *s_addr, *d_addr;
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	if (!src || !dst)
495*4882a593Smuzhiyun 		return 0;
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	s_addr = (const struct sockaddr *)(src + 1);
498*4882a593Smuzhiyun 	d_addr = (const struct sockaddr *)(dst + 1);
499*4882a593Smuzhiyun 	if (s_addr->sa_family != d_addr->sa_family)
500*4882a593Smuzhiyun 		return 0;
501*4882a593Smuzhiyun 	if (s_addr->sa_family != AF_INET
502*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
503*4882a593Smuzhiyun 	    && s_addr->sa_family != AF_INET6
504*4882a593Smuzhiyun #endif
505*4882a593Smuzhiyun 		)
506*4882a593Smuzhiyun 		return 0;
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun 	return 1;
509*4882a593Smuzhiyun }
510*4882a593Smuzhiyun 
parse_exthdrs(struct sk_buff * skb,const struct sadb_msg * hdr,void ** ext_hdrs)511*4882a593Smuzhiyun static int parse_exthdrs(struct sk_buff *skb, const struct sadb_msg *hdr, void **ext_hdrs)
512*4882a593Smuzhiyun {
513*4882a593Smuzhiyun 	const char *p = (char *) hdr;
514*4882a593Smuzhiyun 	int len = skb->len;
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	len -= sizeof(*hdr);
517*4882a593Smuzhiyun 	p += sizeof(*hdr);
518*4882a593Smuzhiyun 	while (len > 0) {
519*4882a593Smuzhiyun 		const struct sadb_ext *ehdr = (const struct sadb_ext *) p;
520*4882a593Smuzhiyun 		uint16_t ext_type;
521*4882a593Smuzhiyun 		int ext_len;
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 		if (len < sizeof(*ehdr))
524*4882a593Smuzhiyun 			return -EINVAL;
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 		ext_len  = ehdr->sadb_ext_len;
527*4882a593Smuzhiyun 		ext_len *= sizeof(uint64_t);
528*4882a593Smuzhiyun 		ext_type = ehdr->sadb_ext_type;
529*4882a593Smuzhiyun 		if (ext_len < sizeof(uint64_t) ||
530*4882a593Smuzhiyun 		    ext_len > len ||
531*4882a593Smuzhiyun 		    ext_type == SADB_EXT_RESERVED)
532*4882a593Smuzhiyun 			return -EINVAL;
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun 		if (ext_type <= SADB_EXT_MAX) {
535*4882a593Smuzhiyun 			int min = (int) sadb_ext_min_len[ext_type];
536*4882a593Smuzhiyun 			if (ext_len < min)
537*4882a593Smuzhiyun 				return -EINVAL;
538*4882a593Smuzhiyun 			if (ext_hdrs[ext_type-1] != NULL)
539*4882a593Smuzhiyun 				return -EINVAL;
540*4882a593Smuzhiyun 			switch (ext_type) {
541*4882a593Smuzhiyun 			case SADB_EXT_ADDRESS_SRC:
542*4882a593Smuzhiyun 			case SADB_EXT_ADDRESS_DST:
543*4882a593Smuzhiyun 			case SADB_EXT_ADDRESS_PROXY:
544*4882a593Smuzhiyun 			case SADB_X_EXT_NAT_T_OA:
545*4882a593Smuzhiyun 				if (verify_address_len(p))
546*4882a593Smuzhiyun 					return -EINVAL;
547*4882a593Smuzhiyun 				break;
548*4882a593Smuzhiyun 			case SADB_X_EXT_SEC_CTX:
549*4882a593Smuzhiyun 				if (verify_sec_ctx_len(p))
550*4882a593Smuzhiyun 					return -EINVAL;
551*4882a593Smuzhiyun 				break;
552*4882a593Smuzhiyun 			case SADB_EXT_KEY_AUTH:
553*4882a593Smuzhiyun 			case SADB_EXT_KEY_ENCRYPT:
554*4882a593Smuzhiyun 				if (verify_key_len(p))
555*4882a593Smuzhiyun 					return -EINVAL;
556*4882a593Smuzhiyun 				break;
557*4882a593Smuzhiyun 			default:
558*4882a593Smuzhiyun 				break;
559*4882a593Smuzhiyun 			}
560*4882a593Smuzhiyun 			ext_hdrs[ext_type-1] = (void *) p;
561*4882a593Smuzhiyun 		}
562*4882a593Smuzhiyun 		p   += ext_len;
563*4882a593Smuzhiyun 		len -= ext_len;
564*4882a593Smuzhiyun 	}
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun 	return 0;
567*4882a593Smuzhiyun }
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun static uint16_t
pfkey_satype2proto(uint8_t satype)570*4882a593Smuzhiyun pfkey_satype2proto(uint8_t satype)
571*4882a593Smuzhiyun {
572*4882a593Smuzhiyun 	switch (satype) {
573*4882a593Smuzhiyun 	case SADB_SATYPE_UNSPEC:
574*4882a593Smuzhiyun 		return IPSEC_PROTO_ANY;
575*4882a593Smuzhiyun 	case SADB_SATYPE_AH:
576*4882a593Smuzhiyun 		return IPPROTO_AH;
577*4882a593Smuzhiyun 	case SADB_SATYPE_ESP:
578*4882a593Smuzhiyun 		return IPPROTO_ESP;
579*4882a593Smuzhiyun 	case SADB_X_SATYPE_IPCOMP:
580*4882a593Smuzhiyun 		return IPPROTO_COMP;
581*4882a593Smuzhiyun 	default:
582*4882a593Smuzhiyun 		return 0;
583*4882a593Smuzhiyun 	}
584*4882a593Smuzhiyun 	/* NOTREACHED */
585*4882a593Smuzhiyun }
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun static uint8_t
pfkey_proto2satype(uint16_t proto)588*4882a593Smuzhiyun pfkey_proto2satype(uint16_t proto)
589*4882a593Smuzhiyun {
590*4882a593Smuzhiyun 	switch (proto) {
591*4882a593Smuzhiyun 	case IPPROTO_AH:
592*4882a593Smuzhiyun 		return SADB_SATYPE_AH;
593*4882a593Smuzhiyun 	case IPPROTO_ESP:
594*4882a593Smuzhiyun 		return SADB_SATYPE_ESP;
595*4882a593Smuzhiyun 	case IPPROTO_COMP:
596*4882a593Smuzhiyun 		return SADB_X_SATYPE_IPCOMP;
597*4882a593Smuzhiyun 	default:
598*4882a593Smuzhiyun 		return 0;
599*4882a593Smuzhiyun 	}
600*4882a593Smuzhiyun 	/* NOTREACHED */
601*4882a593Smuzhiyun }
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun /* BTW, this scheme means that there is no way with PFKEY2 sockets to
604*4882a593Smuzhiyun  * say specifically 'just raw sockets' as we encode them as 255.
605*4882a593Smuzhiyun  */
606*4882a593Smuzhiyun 
pfkey_proto_to_xfrm(uint8_t proto)607*4882a593Smuzhiyun static uint8_t pfkey_proto_to_xfrm(uint8_t proto)
608*4882a593Smuzhiyun {
609*4882a593Smuzhiyun 	return proto == IPSEC_PROTO_ANY ? 0 : proto;
610*4882a593Smuzhiyun }
611*4882a593Smuzhiyun 
pfkey_proto_from_xfrm(uint8_t proto)612*4882a593Smuzhiyun static uint8_t pfkey_proto_from_xfrm(uint8_t proto)
613*4882a593Smuzhiyun {
614*4882a593Smuzhiyun 	return proto ? proto : IPSEC_PROTO_ANY;
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun 
pfkey_sockaddr_len(sa_family_t family)617*4882a593Smuzhiyun static inline int pfkey_sockaddr_len(sa_family_t family)
618*4882a593Smuzhiyun {
619*4882a593Smuzhiyun 	switch (family) {
620*4882a593Smuzhiyun 	case AF_INET:
621*4882a593Smuzhiyun 		return sizeof(struct sockaddr_in);
622*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
623*4882a593Smuzhiyun 	case AF_INET6:
624*4882a593Smuzhiyun 		return sizeof(struct sockaddr_in6);
625*4882a593Smuzhiyun #endif
626*4882a593Smuzhiyun 	}
627*4882a593Smuzhiyun 	return 0;
628*4882a593Smuzhiyun }
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun static
pfkey_sockaddr_extract(const struct sockaddr * sa,xfrm_address_t * xaddr)631*4882a593Smuzhiyun int pfkey_sockaddr_extract(const struct sockaddr *sa, xfrm_address_t *xaddr)
632*4882a593Smuzhiyun {
633*4882a593Smuzhiyun 	switch (sa->sa_family) {
634*4882a593Smuzhiyun 	case AF_INET:
635*4882a593Smuzhiyun 		xaddr->a4 =
636*4882a593Smuzhiyun 			((struct sockaddr_in *)sa)->sin_addr.s_addr;
637*4882a593Smuzhiyun 		return AF_INET;
638*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
639*4882a593Smuzhiyun 	case AF_INET6:
640*4882a593Smuzhiyun 		memcpy(xaddr->a6,
641*4882a593Smuzhiyun 		       &((struct sockaddr_in6 *)sa)->sin6_addr,
642*4882a593Smuzhiyun 		       sizeof(struct in6_addr));
643*4882a593Smuzhiyun 		return AF_INET6;
644*4882a593Smuzhiyun #endif
645*4882a593Smuzhiyun 	}
646*4882a593Smuzhiyun 	return 0;
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun static
pfkey_sadb_addr2xfrm_addr(const struct sadb_address * addr,xfrm_address_t * xaddr)650*4882a593Smuzhiyun int pfkey_sadb_addr2xfrm_addr(const struct sadb_address *addr, xfrm_address_t *xaddr)
651*4882a593Smuzhiyun {
652*4882a593Smuzhiyun 	return pfkey_sockaddr_extract((struct sockaddr *)(addr + 1),
653*4882a593Smuzhiyun 				      xaddr);
654*4882a593Smuzhiyun }
655*4882a593Smuzhiyun 
pfkey_xfrm_state_lookup(struct net * net,const struct sadb_msg * hdr,void * const * ext_hdrs)656*4882a593Smuzhiyun static struct  xfrm_state *pfkey_xfrm_state_lookup(struct net *net, const struct sadb_msg *hdr, void * const *ext_hdrs)
657*4882a593Smuzhiyun {
658*4882a593Smuzhiyun 	const struct sadb_sa *sa;
659*4882a593Smuzhiyun 	const struct sadb_address *addr;
660*4882a593Smuzhiyun 	uint16_t proto;
661*4882a593Smuzhiyun 	unsigned short family;
662*4882a593Smuzhiyun 	xfrm_address_t *xaddr;
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun 	sa = ext_hdrs[SADB_EXT_SA - 1];
665*4882a593Smuzhiyun 	if (sa == NULL)
666*4882a593Smuzhiyun 		return NULL;
667*4882a593Smuzhiyun 
668*4882a593Smuzhiyun 	proto = pfkey_satype2proto(hdr->sadb_msg_satype);
669*4882a593Smuzhiyun 	if (proto == 0)
670*4882a593Smuzhiyun 		return NULL;
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun 	/* sadb_address_len should be checked by caller */
673*4882a593Smuzhiyun 	addr = ext_hdrs[SADB_EXT_ADDRESS_DST - 1];
674*4882a593Smuzhiyun 	if (addr == NULL)
675*4882a593Smuzhiyun 		return NULL;
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun 	family = ((const struct sockaddr *)(addr + 1))->sa_family;
678*4882a593Smuzhiyun 	switch (family) {
679*4882a593Smuzhiyun 	case AF_INET:
680*4882a593Smuzhiyun 		xaddr = (xfrm_address_t *)&((const struct sockaddr_in *)(addr + 1))->sin_addr;
681*4882a593Smuzhiyun 		break;
682*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
683*4882a593Smuzhiyun 	case AF_INET6:
684*4882a593Smuzhiyun 		xaddr = (xfrm_address_t *)&((const struct sockaddr_in6 *)(addr + 1))->sin6_addr;
685*4882a593Smuzhiyun 		break;
686*4882a593Smuzhiyun #endif
687*4882a593Smuzhiyun 	default:
688*4882a593Smuzhiyun 		xaddr = NULL;
689*4882a593Smuzhiyun 	}
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun 	if (!xaddr)
692*4882a593Smuzhiyun 		return NULL;
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun 	return xfrm_state_lookup(net, DUMMY_MARK, xaddr, sa->sadb_sa_spi, proto, family);
695*4882a593Smuzhiyun }
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun #define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1)))
698*4882a593Smuzhiyun 
699*4882a593Smuzhiyun static int
pfkey_sockaddr_size(sa_family_t family)700*4882a593Smuzhiyun pfkey_sockaddr_size(sa_family_t family)
701*4882a593Smuzhiyun {
702*4882a593Smuzhiyun 	return PFKEY_ALIGN8(pfkey_sockaddr_len(family));
703*4882a593Smuzhiyun }
704*4882a593Smuzhiyun 
pfkey_mode_from_xfrm(int mode)705*4882a593Smuzhiyun static inline int pfkey_mode_from_xfrm(int mode)
706*4882a593Smuzhiyun {
707*4882a593Smuzhiyun 	switch(mode) {
708*4882a593Smuzhiyun 	case XFRM_MODE_TRANSPORT:
709*4882a593Smuzhiyun 		return IPSEC_MODE_TRANSPORT;
710*4882a593Smuzhiyun 	case XFRM_MODE_TUNNEL:
711*4882a593Smuzhiyun 		return IPSEC_MODE_TUNNEL;
712*4882a593Smuzhiyun 	case XFRM_MODE_BEET:
713*4882a593Smuzhiyun 		return IPSEC_MODE_BEET;
714*4882a593Smuzhiyun 	default:
715*4882a593Smuzhiyun 		return -1;
716*4882a593Smuzhiyun 	}
717*4882a593Smuzhiyun }
718*4882a593Smuzhiyun 
pfkey_mode_to_xfrm(int mode)719*4882a593Smuzhiyun static inline int pfkey_mode_to_xfrm(int mode)
720*4882a593Smuzhiyun {
721*4882a593Smuzhiyun 	switch(mode) {
722*4882a593Smuzhiyun 	case IPSEC_MODE_ANY:	/*XXX*/
723*4882a593Smuzhiyun 	case IPSEC_MODE_TRANSPORT:
724*4882a593Smuzhiyun 		return XFRM_MODE_TRANSPORT;
725*4882a593Smuzhiyun 	case IPSEC_MODE_TUNNEL:
726*4882a593Smuzhiyun 		return XFRM_MODE_TUNNEL;
727*4882a593Smuzhiyun 	case IPSEC_MODE_BEET:
728*4882a593Smuzhiyun 		return XFRM_MODE_BEET;
729*4882a593Smuzhiyun 	default:
730*4882a593Smuzhiyun 		return -1;
731*4882a593Smuzhiyun 	}
732*4882a593Smuzhiyun }
733*4882a593Smuzhiyun 
pfkey_sockaddr_fill(const xfrm_address_t * xaddr,__be16 port,struct sockaddr * sa,unsigned short family)734*4882a593Smuzhiyun static unsigned int pfkey_sockaddr_fill(const xfrm_address_t *xaddr, __be16 port,
735*4882a593Smuzhiyun 					struct sockaddr *sa,
736*4882a593Smuzhiyun 					unsigned short family)
737*4882a593Smuzhiyun {
738*4882a593Smuzhiyun 	switch (family) {
739*4882a593Smuzhiyun 	case AF_INET:
740*4882a593Smuzhiyun 	    {
741*4882a593Smuzhiyun 		struct sockaddr_in *sin = (struct sockaddr_in *)sa;
742*4882a593Smuzhiyun 		sin->sin_family = AF_INET;
743*4882a593Smuzhiyun 		sin->sin_port = port;
744*4882a593Smuzhiyun 		sin->sin_addr.s_addr = xaddr->a4;
745*4882a593Smuzhiyun 		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
746*4882a593Smuzhiyun 		return 32;
747*4882a593Smuzhiyun 	    }
748*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
749*4882a593Smuzhiyun 	case AF_INET6:
750*4882a593Smuzhiyun 	    {
751*4882a593Smuzhiyun 		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
752*4882a593Smuzhiyun 		sin6->sin6_family = AF_INET6;
753*4882a593Smuzhiyun 		sin6->sin6_port = port;
754*4882a593Smuzhiyun 		sin6->sin6_flowinfo = 0;
755*4882a593Smuzhiyun 		sin6->sin6_addr = xaddr->in6;
756*4882a593Smuzhiyun 		sin6->sin6_scope_id = 0;
757*4882a593Smuzhiyun 		return 128;
758*4882a593Smuzhiyun 	    }
759*4882a593Smuzhiyun #endif
760*4882a593Smuzhiyun 	}
761*4882a593Smuzhiyun 	return 0;
762*4882a593Smuzhiyun }
763*4882a593Smuzhiyun 
__pfkey_xfrm_state2msg(const struct xfrm_state * x,int add_keys,int hsc)764*4882a593Smuzhiyun static struct sk_buff *__pfkey_xfrm_state2msg(const struct xfrm_state *x,
765*4882a593Smuzhiyun 					      int add_keys, int hsc)
766*4882a593Smuzhiyun {
767*4882a593Smuzhiyun 	struct sk_buff *skb;
768*4882a593Smuzhiyun 	struct sadb_msg *hdr;
769*4882a593Smuzhiyun 	struct sadb_sa *sa;
770*4882a593Smuzhiyun 	struct sadb_lifetime *lifetime;
771*4882a593Smuzhiyun 	struct sadb_address *addr;
772*4882a593Smuzhiyun 	struct sadb_key *key;
773*4882a593Smuzhiyun 	struct sadb_x_sa2 *sa2;
774*4882a593Smuzhiyun 	struct sadb_x_sec_ctx *sec_ctx;
775*4882a593Smuzhiyun 	struct xfrm_sec_ctx *xfrm_ctx;
776*4882a593Smuzhiyun 	int ctx_size = 0;
777*4882a593Smuzhiyun 	int size;
778*4882a593Smuzhiyun 	int auth_key_size = 0;
779*4882a593Smuzhiyun 	int encrypt_key_size = 0;
780*4882a593Smuzhiyun 	int sockaddr_size;
781*4882a593Smuzhiyun 	struct xfrm_encap_tmpl *natt = NULL;
782*4882a593Smuzhiyun 	int mode;
783*4882a593Smuzhiyun 
784*4882a593Smuzhiyun 	/* address family check */
785*4882a593Smuzhiyun 	sockaddr_size = pfkey_sockaddr_size(x->props.family);
786*4882a593Smuzhiyun 	if (!sockaddr_size)
787*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
788*4882a593Smuzhiyun 
789*4882a593Smuzhiyun 	/* base, SA, (lifetime (HSC),) address(SD), (address(P),)
790*4882a593Smuzhiyun 	   key(AE), (identity(SD),) (sensitivity)> */
791*4882a593Smuzhiyun 	size = sizeof(struct sadb_msg) +sizeof(struct sadb_sa) +
792*4882a593Smuzhiyun 		sizeof(struct sadb_lifetime) +
793*4882a593Smuzhiyun 		((hsc & 1) ? sizeof(struct sadb_lifetime) : 0) +
794*4882a593Smuzhiyun 		((hsc & 2) ? sizeof(struct sadb_lifetime) : 0) +
795*4882a593Smuzhiyun 			sizeof(struct sadb_address)*2 +
796*4882a593Smuzhiyun 				sockaddr_size*2 +
797*4882a593Smuzhiyun 					sizeof(struct sadb_x_sa2);
798*4882a593Smuzhiyun 
799*4882a593Smuzhiyun 	if ((xfrm_ctx = x->security)) {
800*4882a593Smuzhiyun 		ctx_size = PFKEY_ALIGN8(xfrm_ctx->ctx_len);
801*4882a593Smuzhiyun 		size += sizeof(struct sadb_x_sec_ctx) + ctx_size;
802*4882a593Smuzhiyun 	}
803*4882a593Smuzhiyun 
804*4882a593Smuzhiyun 	/* identity & sensitivity */
805*4882a593Smuzhiyun 	if (!xfrm_addr_equal(&x->sel.saddr, &x->props.saddr, x->props.family))
806*4882a593Smuzhiyun 		size += sizeof(struct sadb_address) + sockaddr_size;
807*4882a593Smuzhiyun 
808*4882a593Smuzhiyun 	if (add_keys) {
809*4882a593Smuzhiyun 		if (x->aalg && x->aalg->alg_key_len) {
810*4882a593Smuzhiyun 			auth_key_size =
811*4882a593Smuzhiyun 				PFKEY_ALIGN8((x->aalg->alg_key_len + 7) / 8);
812*4882a593Smuzhiyun 			size += sizeof(struct sadb_key) + auth_key_size;
813*4882a593Smuzhiyun 		}
814*4882a593Smuzhiyun 		if (x->ealg && x->ealg->alg_key_len) {
815*4882a593Smuzhiyun 			encrypt_key_size =
816*4882a593Smuzhiyun 				PFKEY_ALIGN8((x->ealg->alg_key_len+7) / 8);
817*4882a593Smuzhiyun 			size += sizeof(struct sadb_key) + encrypt_key_size;
818*4882a593Smuzhiyun 		}
819*4882a593Smuzhiyun 	}
820*4882a593Smuzhiyun 	if (x->encap)
821*4882a593Smuzhiyun 		natt = x->encap;
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun 	if (natt && natt->encap_type) {
824*4882a593Smuzhiyun 		size += sizeof(struct sadb_x_nat_t_type);
825*4882a593Smuzhiyun 		size += sizeof(struct sadb_x_nat_t_port);
826*4882a593Smuzhiyun 		size += sizeof(struct sadb_x_nat_t_port);
827*4882a593Smuzhiyun 	}
828*4882a593Smuzhiyun 
829*4882a593Smuzhiyun 	skb =  alloc_skb(size + 16, GFP_ATOMIC);
830*4882a593Smuzhiyun 	if (skb == NULL)
831*4882a593Smuzhiyun 		return ERR_PTR(-ENOBUFS);
832*4882a593Smuzhiyun 
833*4882a593Smuzhiyun 	/* call should fill header later */
834*4882a593Smuzhiyun 	hdr = skb_put(skb, sizeof(struct sadb_msg));
835*4882a593Smuzhiyun 	memset(hdr, 0, size);	/* XXX do we need this ? */
836*4882a593Smuzhiyun 	hdr->sadb_msg_len = size / sizeof(uint64_t);
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun 	/* sa */
839*4882a593Smuzhiyun 	sa = skb_put(skb, sizeof(struct sadb_sa));
840*4882a593Smuzhiyun 	sa->sadb_sa_len = sizeof(struct sadb_sa)/sizeof(uint64_t);
841*4882a593Smuzhiyun 	sa->sadb_sa_exttype = SADB_EXT_SA;
842*4882a593Smuzhiyun 	sa->sadb_sa_spi = x->id.spi;
843*4882a593Smuzhiyun 	sa->sadb_sa_replay = x->props.replay_window;
844*4882a593Smuzhiyun 	switch (x->km.state) {
845*4882a593Smuzhiyun 	case XFRM_STATE_VALID:
846*4882a593Smuzhiyun 		sa->sadb_sa_state = x->km.dying ?
847*4882a593Smuzhiyun 			SADB_SASTATE_DYING : SADB_SASTATE_MATURE;
848*4882a593Smuzhiyun 		break;
849*4882a593Smuzhiyun 	case XFRM_STATE_ACQ:
850*4882a593Smuzhiyun 		sa->sadb_sa_state = SADB_SASTATE_LARVAL;
851*4882a593Smuzhiyun 		break;
852*4882a593Smuzhiyun 	default:
853*4882a593Smuzhiyun 		sa->sadb_sa_state = SADB_SASTATE_DEAD;
854*4882a593Smuzhiyun 		break;
855*4882a593Smuzhiyun 	}
856*4882a593Smuzhiyun 	sa->sadb_sa_auth = 0;
857*4882a593Smuzhiyun 	if (x->aalg) {
858*4882a593Smuzhiyun 		struct xfrm_algo_desc *a = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
859*4882a593Smuzhiyun 		sa->sadb_sa_auth = (a && a->pfkey_supported) ?
860*4882a593Smuzhiyun 					a->desc.sadb_alg_id : 0;
861*4882a593Smuzhiyun 	}
862*4882a593Smuzhiyun 	sa->sadb_sa_encrypt = 0;
863*4882a593Smuzhiyun 	BUG_ON(x->ealg && x->calg);
864*4882a593Smuzhiyun 	if (x->ealg) {
865*4882a593Smuzhiyun 		struct xfrm_algo_desc *a = xfrm_ealg_get_byname(x->ealg->alg_name, 0);
866*4882a593Smuzhiyun 		sa->sadb_sa_encrypt = (a && a->pfkey_supported) ?
867*4882a593Smuzhiyun 					a->desc.sadb_alg_id : 0;
868*4882a593Smuzhiyun 	}
869*4882a593Smuzhiyun 	/* KAME compatible: sadb_sa_encrypt is overloaded with calg id */
870*4882a593Smuzhiyun 	if (x->calg) {
871*4882a593Smuzhiyun 		struct xfrm_algo_desc *a = xfrm_calg_get_byname(x->calg->alg_name, 0);
872*4882a593Smuzhiyun 		sa->sadb_sa_encrypt = (a && a->pfkey_supported) ?
873*4882a593Smuzhiyun 					a->desc.sadb_alg_id : 0;
874*4882a593Smuzhiyun 	}
875*4882a593Smuzhiyun 
876*4882a593Smuzhiyun 	sa->sadb_sa_flags = 0;
877*4882a593Smuzhiyun 	if (x->props.flags & XFRM_STATE_NOECN)
878*4882a593Smuzhiyun 		sa->sadb_sa_flags |= SADB_SAFLAGS_NOECN;
879*4882a593Smuzhiyun 	if (x->props.flags & XFRM_STATE_DECAP_DSCP)
880*4882a593Smuzhiyun 		sa->sadb_sa_flags |= SADB_SAFLAGS_DECAP_DSCP;
881*4882a593Smuzhiyun 	if (x->props.flags & XFRM_STATE_NOPMTUDISC)
882*4882a593Smuzhiyun 		sa->sadb_sa_flags |= SADB_SAFLAGS_NOPMTUDISC;
883*4882a593Smuzhiyun 
884*4882a593Smuzhiyun 	/* hard time */
885*4882a593Smuzhiyun 	if (hsc & 2) {
886*4882a593Smuzhiyun 		lifetime = skb_put(skb, sizeof(struct sadb_lifetime));
887*4882a593Smuzhiyun 		lifetime->sadb_lifetime_len =
888*4882a593Smuzhiyun 			sizeof(struct sadb_lifetime)/sizeof(uint64_t);
889*4882a593Smuzhiyun 		lifetime->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
890*4882a593Smuzhiyun 		lifetime->sadb_lifetime_allocations =  _X2KEY(x->lft.hard_packet_limit);
891*4882a593Smuzhiyun 		lifetime->sadb_lifetime_bytes = _X2KEY(x->lft.hard_byte_limit);
892*4882a593Smuzhiyun 		lifetime->sadb_lifetime_addtime = x->lft.hard_add_expires_seconds;
893*4882a593Smuzhiyun 		lifetime->sadb_lifetime_usetime = x->lft.hard_use_expires_seconds;
894*4882a593Smuzhiyun 	}
895*4882a593Smuzhiyun 	/* soft time */
896*4882a593Smuzhiyun 	if (hsc & 1) {
897*4882a593Smuzhiyun 		lifetime = skb_put(skb, sizeof(struct sadb_lifetime));
898*4882a593Smuzhiyun 		lifetime->sadb_lifetime_len =
899*4882a593Smuzhiyun 			sizeof(struct sadb_lifetime)/sizeof(uint64_t);
900*4882a593Smuzhiyun 		lifetime->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
901*4882a593Smuzhiyun 		lifetime->sadb_lifetime_allocations =  _X2KEY(x->lft.soft_packet_limit);
902*4882a593Smuzhiyun 		lifetime->sadb_lifetime_bytes = _X2KEY(x->lft.soft_byte_limit);
903*4882a593Smuzhiyun 		lifetime->sadb_lifetime_addtime = x->lft.soft_add_expires_seconds;
904*4882a593Smuzhiyun 		lifetime->sadb_lifetime_usetime = x->lft.soft_use_expires_seconds;
905*4882a593Smuzhiyun 	}
906*4882a593Smuzhiyun 	/* current time */
907*4882a593Smuzhiyun 	lifetime = skb_put(skb, sizeof(struct sadb_lifetime));
908*4882a593Smuzhiyun 	lifetime->sadb_lifetime_len =
909*4882a593Smuzhiyun 		sizeof(struct sadb_lifetime)/sizeof(uint64_t);
910*4882a593Smuzhiyun 	lifetime->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT;
911*4882a593Smuzhiyun 	lifetime->sadb_lifetime_allocations = x->curlft.packets;
912*4882a593Smuzhiyun 	lifetime->sadb_lifetime_bytes = x->curlft.bytes;
913*4882a593Smuzhiyun 	lifetime->sadb_lifetime_addtime = x->curlft.add_time;
914*4882a593Smuzhiyun 	lifetime->sadb_lifetime_usetime = x->curlft.use_time;
915*4882a593Smuzhiyun 	/* src address */
916*4882a593Smuzhiyun 	addr = skb_put(skb, sizeof(struct sadb_address) + sockaddr_size);
917*4882a593Smuzhiyun 	addr->sadb_address_len =
918*4882a593Smuzhiyun 		(sizeof(struct sadb_address)+sockaddr_size)/
919*4882a593Smuzhiyun 			sizeof(uint64_t);
920*4882a593Smuzhiyun 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
921*4882a593Smuzhiyun 	/* "if the ports are non-zero, then the sadb_address_proto field,
922*4882a593Smuzhiyun 	   normally zero, MUST be filled in with the transport
923*4882a593Smuzhiyun 	   protocol's number." - RFC2367 */
924*4882a593Smuzhiyun 	addr->sadb_address_proto = 0;
925*4882a593Smuzhiyun 	addr->sadb_address_reserved = 0;
926*4882a593Smuzhiyun 
927*4882a593Smuzhiyun 	addr->sadb_address_prefixlen =
928*4882a593Smuzhiyun 		pfkey_sockaddr_fill(&x->props.saddr, 0,
929*4882a593Smuzhiyun 				    (struct sockaddr *) (addr + 1),
930*4882a593Smuzhiyun 				    x->props.family);
931*4882a593Smuzhiyun 	BUG_ON(!addr->sadb_address_prefixlen);
932*4882a593Smuzhiyun 
933*4882a593Smuzhiyun 	/* dst address */
934*4882a593Smuzhiyun 	addr = skb_put(skb, sizeof(struct sadb_address) + sockaddr_size);
935*4882a593Smuzhiyun 	addr->sadb_address_len =
936*4882a593Smuzhiyun 		(sizeof(struct sadb_address)+sockaddr_size)/
937*4882a593Smuzhiyun 			sizeof(uint64_t);
938*4882a593Smuzhiyun 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
939*4882a593Smuzhiyun 	addr->sadb_address_proto = 0;
940*4882a593Smuzhiyun 	addr->sadb_address_reserved = 0;
941*4882a593Smuzhiyun 
942*4882a593Smuzhiyun 	addr->sadb_address_prefixlen =
943*4882a593Smuzhiyun 		pfkey_sockaddr_fill(&x->id.daddr, 0,
944*4882a593Smuzhiyun 				    (struct sockaddr *) (addr + 1),
945*4882a593Smuzhiyun 				    x->props.family);
946*4882a593Smuzhiyun 	BUG_ON(!addr->sadb_address_prefixlen);
947*4882a593Smuzhiyun 
948*4882a593Smuzhiyun 	if (!xfrm_addr_equal(&x->sel.saddr, &x->props.saddr,
949*4882a593Smuzhiyun 			     x->props.family)) {
950*4882a593Smuzhiyun 		addr = skb_put(skb,
951*4882a593Smuzhiyun 			       sizeof(struct sadb_address) + sockaddr_size);
952*4882a593Smuzhiyun 		addr->sadb_address_len =
953*4882a593Smuzhiyun 			(sizeof(struct sadb_address)+sockaddr_size)/
954*4882a593Smuzhiyun 			sizeof(uint64_t);
955*4882a593Smuzhiyun 		addr->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY;
956*4882a593Smuzhiyun 		addr->sadb_address_proto =
957*4882a593Smuzhiyun 			pfkey_proto_from_xfrm(x->sel.proto);
958*4882a593Smuzhiyun 		addr->sadb_address_prefixlen = x->sel.prefixlen_s;
959*4882a593Smuzhiyun 		addr->sadb_address_reserved = 0;
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun 		pfkey_sockaddr_fill(&x->sel.saddr, x->sel.sport,
962*4882a593Smuzhiyun 				    (struct sockaddr *) (addr + 1),
963*4882a593Smuzhiyun 				    x->props.family);
964*4882a593Smuzhiyun 	}
965*4882a593Smuzhiyun 
966*4882a593Smuzhiyun 	/* auth key */
967*4882a593Smuzhiyun 	if (add_keys && auth_key_size) {
968*4882a593Smuzhiyun 		key = skb_put(skb, sizeof(struct sadb_key) + auth_key_size);
969*4882a593Smuzhiyun 		key->sadb_key_len = (sizeof(struct sadb_key) + auth_key_size) /
970*4882a593Smuzhiyun 			sizeof(uint64_t);
971*4882a593Smuzhiyun 		key->sadb_key_exttype = SADB_EXT_KEY_AUTH;
972*4882a593Smuzhiyun 		key->sadb_key_bits = x->aalg->alg_key_len;
973*4882a593Smuzhiyun 		key->sadb_key_reserved = 0;
974*4882a593Smuzhiyun 		memcpy(key + 1, x->aalg->alg_key, (x->aalg->alg_key_len+7)/8);
975*4882a593Smuzhiyun 	}
976*4882a593Smuzhiyun 	/* encrypt key */
977*4882a593Smuzhiyun 	if (add_keys && encrypt_key_size) {
978*4882a593Smuzhiyun 		key = skb_put(skb, sizeof(struct sadb_key) + encrypt_key_size);
979*4882a593Smuzhiyun 		key->sadb_key_len = (sizeof(struct sadb_key) +
980*4882a593Smuzhiyun 				     encrypt_key_size) / sizeof(uint64_t);
981*4882a593Smuzhiyun 		key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
982*4882a593Smuzhiyun 		key->sadb_key_bits = x->ealg->alg_key_len;
983*4882a593Smuzhiyun 		key->sadb_key_reserved = 0;
984*4882a593Smuzhiyun 		memcpy(key + 1, x->ealg->alg_key,
985*4882a593Smuzhiyun 		       (x->ealg->alg_key_len+7)/8);
986*4882a593Smuzhiyun 	}
987*4882a593Smuzhiyun 
988*4882a593Smuzhiyun 	/* sa */
989*4882a593Smuzhiyun 	sa2 = skb_put(skb, sizeof(struct sadb_x_sa2));
990*4882a593Smuzhiyun 	sa2->sadb_x_sa2_len = sizeof(struct sadb_x_sa2)/sizeof(uint64_t);
991*4882a593Smuzhiyun 	sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
992*4882a593Smuzhiyun 	if ((mode = pfkey_mode_from_xfrm(x->props.mode)) < 0) {
993*4882a593Smuzhiyun 		kfree_skb(skb);
994*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
995*4882a593Smuzhiyun 	}
996*4882a593Smuzhiyun 	sa2->sadb_x_sa2_mode = mode;
997*4882a593Smuzhiyun 	sa2->sadb_x_sa2_reserved1 = 0;
998*4882a593Smuzhiyun 	sa2->sadb_x_sa2_reserved2 = 0;
999*4882a593Smuzhiyun 	sa2->sadb_x_sa2_sequence = 0;
1000*4882a593Smuzhiyun 	sa2->sadb_x_sa2_reqid = x->props.reqid;
1001*4882a593Smuzhiyun 
1002*4882a593Smuzhiyun 	if (natt && natt->encap_type) {
1003*4882a593Smuzhiyun 		struct sadb_x_nat_t_type *n_type;
1004*4882a593Smuzhiyun 		struct sadb_x_nat_t_port *n_port;
1005*4882a593Smuzhiyun 
1006*4882a593Smuzhiyun 		/* type */
1007*4882a593Smuzhiyun 		n_type = skb_put(skb, sizeof(*n_type));
1008*4882a593Smuzhiyun 		n_type->sadb_x_nat_t_type_len = sizeof(*n_type)/sizeof(uint64_t);
1009*4882a593Smuzhiyun 		n_type->sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE;
1010*4882a593Smuzhiyun 		n_type->sadb_x_nat_t_type_type = natt->encap_type;
1011*4882a593Smuzhiyun 		n_type->sadb_x_nat_t_type_reserved[0] = 0;
1012*4882a593Smuzhiyun 		n_type->sadb_x_nat_t_type_reserved[1] = 0;
1013*4882a593Smuzhiyun 		n_type->sadb_x_nat_t_type_reserved[2] = 0;
1014*4882a593Smuzhiyun 
1015*4882a593Smuzhiyun 		/* source port */
1016*4882a593Smuzhiyun 		n_port = skb_put(skb, sizeof(*n_port));
1017*4882a593Smuzhiyun 		n_port->sadb_x_nat_t_port_len = sizeof(*n_port)/sizeof(uint64_t);
1018*4882a593Smuzhiyun 		n_port->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_SPORT;
1019*4882a593Smuzhiyun 		n_port->sadb_x_nat_t_port_port = natt->encap_sport;
1020*4882a593Smuzhiyun 		n_port->sadb_x_nat_t_port_reserved = 0;
1021*4882a593Smuzhiyun 
1022*4882a593Smuzhiyun 		/* dest port */
1023*4882a593Smuzhiyun 		n_port = skb_put(skb, sizeof(*n_port));
1024*4882a593Smuzhiyun 		n_port->sadb_x_nat_t_port_len = sizeof(*n_port)/sizeof(uint64_t);
1025*4882a593Smuzhiyun 		n_port->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_DPORT;
1026*4882a593Smuzhiyun 		n_port->sadb_x_nat_t_port_port = natt->encap_dport;
1027*4882a593Smuzhiyun 		n_port->sadb_x_nat_t_port_reserved = 0;
1028*4882a593Smuzhiyun 	}
1029*4882a593Smuzhiyun 
1030*4882a593Smuzhiyun 	/* security context */
1031*4882a593Smuzhiyun 	if (xfrm_ctx) {
1032*4882a593Smuzhiyun 		sec_ctx = skb_put(skb,
1033*4882a593Smuzhiyun 				  sizeof(struct sadb_x_sec_ctx) + ctx_size);
1034*4882a593Smuzhiyun 		sec_ctx->sadb_x_sec_len =
1035*4882a593Smuzhiyun 		  (sizeof(struct sadb_x_sec_ctx) + ctx_size) / sizeof(uint64_t);
1036*4882a593Smuzhiyun 		sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
1037*4882a593Smuzhiyun 		sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi;
1038*4882a593Smuzhiyun 		sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg;
1039*4882a593Smuzhiyun 		sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len;
1040*4882a593Smuzhiyun 		memcpy(sec_ctx + 1, xfrm_ctx->ctx_str,
1041*4882a593Smuzhiyun 		       xfrm_ctx->ctx_len);
1042*4882a593Smuzhiyun 	}
1043*4882a593Smuzhiyun 
1044*4882a593Smuzhiyun 	return skb;
1045*4882a593Smuzhiyun }
1046*4882a593Smuzhiyun 
1047*4882a593Smuzhiyun 
pfkey_xfrm_state2msg(const struct xfrm_state * x)1048*4882a593Smuzhiyun static inline struct sk_buff *pfkey_xfrm_state2msg(const struct xfrm_state *x)
1049*4882a593Smuzhiyun {
1050*4882a593Smuzhiyun 	struct sk_buff *skb;
1051*4882a593Smuzhiyun 
1052*4882a593Smuzhiyun 	skb = __pfkey_xfrm_state2msg(x, 1, 3);
1053*4882a593Smuzhiyun 
1054*4882a593Smuzhiyun 	return skb;
1055*4882a593Smuzhiyun }
1056*4882a593Smuzhiyun 
pfkey_xfrm_state2msg_expire(const struct xfrm_state * x,int hsc)1057*4882a593Smuzhiyun static inline struct sk_buff *pfkey_xfrm_state2msg_expire(const struct xfrm_state *x,
1058*4882a593Smuzhiyun 							  int hsc)
1059*4882a593Smuzhiyun {
1060*4882a593Smuzhiyun 	return __pfkey_xfrm_state2msg(x, 0, hsc);
1061*4882a593Smuzhiyun }
1062*4882a593Smuzhiyun 
pfkey_msg2xfrm_state(struct net * net,const struct sadb_msg * hdr,void * const * ext_hdrs)1063*4882a593Smuzhiyun static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
1064*4882a593Smuzhiyun 						const struct sadb_msg *hdr,
1065*4882a593Smuzhiyun 						void * const *ext_hdrs)
1066*4882a593Smuzhiyun {
1067*4882a593Smuzhiyun 	struct xfrm_state *x;
1068*4882a593Smuzhiyun 	const struct sadb_lifetime *lifetime;
1069*4882a593Smuzhiyun 	const struct sadb_sa *sa;
1070*4882a593Smuzhiyun 	const struct sadb_key *key;
1071*4882a593Smuzhiyun 	const struct sadb_x_sec_ctx *sec_ctx;
1072*4882a593Smuzhiyun 	uint16_t proto;
1073*4882a593Smuzhiyun 	int err;
1074*4882a593Smuzhiyun 
1075*4882a593Smuzhiyun 
1076*4882a593Smuzhiyun 	sa = ext_hdrs[SADB_EXT_SA - 1];
1077*4882a593Smuzhiyun 	if (!sa ||
1078*4882a593Smuzhiyun 	    !present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
1079*4882a593Smuzhiyun 				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]))
1080*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
1081*4882a593Smuzhiyun 	if (hdr->sadb_msg_satype == SADB_SATYPE_ESP &&
1082*4882a593Smuzhiyun 	    !ext_hdrs[SADB_EXT_KEY_ENCRYPT-1])
1083*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
1084*4882a593Smuzhiyun 	if (hdr->sadb_msg_satype == SADB_SATYPE_AH &&
1085*4882a593Smuzhiyun 	    !ext_hdrs[SADB_EXT_KEY_AUTH-1])
1086*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
1087*4882a593Smuzhiyun 	if (!!ext_hdrs[SADB_EXT_LIFETIME_HARD-1] !=
1088*4882a593Smuzhiyun 	    !!ext_hdrs[SADB_EXT_LIFETIME_SOFT-1])
1089*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
1090*4882a593Smuzhiyun 
1091*4882a593Smuzhiyun 	proto = pfkey_satype2proto(hdr->sadb_msg_satype);
1092*4882a593Smuzhiyun 	if (proto == 0)
1093*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
1094*4882a593Smuzhiyun 
1095*4882a593Smuzhiyun 	/* default error is no buffer space */
1096*4882a593Smuzhiyun 	err = -ENOBUFS;
1097*4882a593Smuzhiyun 
1098*4882a593Smuzhiyun 	/* RFC2367:
1099*4882a593Smuzhiyun 
1100*4882a593Smuzhiyun    Only SADB_SASTATE_MATURE SAs may be submitted in an SADB_ADD message.
1101*4882a593Smuzhiyun    SADB_SASTATE_LARVAL SAs are created by SADB_GETSPI and it is not
1102*4882a593Smuzhiyun    sensible to add a new SA in the DYING or SADB_SASTATE_DEAD state.
1103*4882a593Smuzhiyun    Therefore, the sadb_sa_state field of all submitted SAs MUST be
1104*4882a593Smuzhiyun    SADB_SASTATE_MATURE and the kernel MUST return an error if this is
1105*4882a593Smuzhiyun    not true.
1106*4882a593Smuzhiyun 
1107*4882a593Smuzhiyun 	   However, KAME setkey always uses SADB_SASTATE_LARVAL.
1108*4882a593Smuzhiyun 	   Hence, we have to _ignore_ sadb_sa_state, which is also reasonable.
1109*4882a593Smuzhiyun 	 */
1110*4882a593Smuzhiyun 	if (sa->sadb_sa_auth > SADB_AALG_MAX ||
1111*4882a593Smuzhiyun 	    (hdr->sadb_msg_satype == SADB_X_SATYPE_IPCOMP &&
1112*4882a593Smuzhiyun 	     sa->sadb_sa_encrypt > SADB_X_CALG_MAX) ||
1113*4882a593Smuzhiyun 	    sa->sadb_sa_encrypt > SADB_EALG_MAX)
1114*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
1115*4882a593Smuzhiyun 	key = ext_hdrs[SADB_EXT_KEY_AUTH - 1];
1116*4882a593Smuzhiyun 	if (key != NULL &&
1117*4882a593Smuzhiyun 	    sa->sadb_sa_auth != SADB_X_AALG_NULL &&
1118*4882a593Smuzhiyun 	    key->sadb_key_bits == 0)
1119*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
1120*4882a593Smuzhiyun 	key = ext_hdrs[SADB_EXT_KEY_ENCRYPT-1];
1121*4882a593Smuzhiyun 	if (key != NULL &&
1122*4882a593Smuzhiyun 	    sa->sadb_sa_encrypt != SADB_EALG_NULL &&
1123*4882a593Smuzhiyun 	    key->sadb_key_bits == 0)
1124*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
1125*4882a593Smuzhiyun 
1126*4882a593Smuzhiyun 	x = xfrm_state_alloc(net);
1127*4882a593Smuzhiyun 	if (x == NULL)
1128*4882a593Smuzhiyun 		return ERR_PTR(-ENOBUFS);
1129*4882a593Smuzhiyun 
1130*4882a593Smuzhiyun 	x->id.proto = proto;
1131*4882a593Smuzhiyun 	x->id.spi = sa->sadb_sa_spi;
1132*4882a593Smuzhiyun 	x->props.replay_window = min_t(unsigned int, sa->sadb_sa_replay,
1133*4882a593Smuzhiyun 					(sizeof(x->replay.bitmap) * 8));
1134*4882a593Smuzhiyun 	if (sa->sadb_sa_flags & SADB_SAFLAGS_NOECN)
1135*4882a593Smuzhiyun 		x->props.flags |= XFRM_STATE_NOECN;
1136*4882a593Smuzhiyun 	if (sa->sadb_sa_flags & SADB_SAFLAGS_DECAP_DSCP)
1137*4882a593Smuzhiyun 		x->props.flags |= XFRM_STATE_DECAP_DSCP;
1138*4882a593Smuzhiyun 	if (sa->sadb_sa_flags & SADB_SAFLAGS_NOPMTUDISC)
1139*4882a593Smuzhiyun 		x->props.flags |= XFRM_STATE_NOPMTUDISC;
1140*4882a593Smuzhiyun 
1141*4882a593Smuzhiyun 	lifetime = ext_hdrs[SADB_EXT_LIFETIME_HARD - 1];
1142*4882a593Smuzhiyun 	if (lifetime != NULL) {
1143*4882a593Smuzhiyun 		x->lft.hard_packet_limit = _KEY2X(lifetime->sadb_lifetime_allocations);
1144*4882a593Smuzhiyun 		x->lft.hard_byte_limit = _KEY2X(lifetime->sadb_lifetime_bytes);
1145*4882a593Smuzhiyun 		x->lft.hard_add_expires_seconds = lifetime->sadb_lifetime_addtime;
1146*4882a593Smuzhiyun 		x->lft.hard_use_expires_seconds = lifetime->sadb_lifetime_usetime;
1147*4882a593Smuzhiyun 	}
1148*4882a593Smuzhiyun 	lifetime = ext_hdrs[SADB_EXT_LIFETIME_SOFT - 1];
1149*4882a593Smuzhiyun 	if (lifetime != NULL) {
1150*4882a593Smuzhiyun 		x->lft.soft_packet_limit = _KEY2X(lifetime->sadb_lifetime_allocations);
1151*4882a593Smuzhiyun 		x->lft.soft_byte_limit = _KEY2X(lifetime->sadb_lifetime_bytes);
1152*4882a593Smuzhiyun 		x->lft.soft_add_expires_seconds = lifetime->sadb_lifetime_addtime;
1153*4882a593Smuzhiyun 		x->lft.soft_use_expires_seconds = lifetime->sadb_lifetime_usetime;
1154*4882a593Smuzhiyun 	}
1155*4882a593Smuzhiyun 
1156*4882a593Smuzhiyun 	sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1];
1157*4882a593Smuzhiyun 	if (sec_ctx != NULL) {
1158*4882a593Smuzhiyun 		struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx, GFP_KERNEL);
1159*4882a593Smuzhiyun 
1160*4882a593Smuzhiyun 		if (!uctx)
1161*4882a593Smuzhiyun 			goto out;
1162*4882a593Smuzhiyun 
1163*4882a593Smuzhiyun 		err = security_xfrm_state_alloc(x, uctx);
1164*4882a593Smuzhiyun 		kfree(uctx);
1165*4882a593Smuzhiyun 
1166*4882a593Smuzhiyun 		if (err)
1167*4882a593Smuzhiyun 			goto out;
1168*4882a593Smuzhiyun 	}
1169*4882a593Smuzhiyun 
1170*4882a593Smuzhiyun 	err = -ENOBUFS;
1171*4882a593Smuzhiyun 	key = ext_hdrs[SADB_EXT_KEY_AUTH - 1];
1172*4882a593Smuzhiyun 	if (sa->sadb_sa_auth) {
1173*4882a593Smuzhiyun 		int keysize = 0;
1174*4882a593Smuzhiyun 		struct xfrm_algo_desc *a = xfrm_aalg_get_byid(sa->sadb_sa_auth);
1175*4882a593Smuzhiyun 		if (!a || !a->pfkey_supported) {
1176*4882a593Smuzhiyun 			err = -ENOSYS;
1177*4882a593Smuzhiyun 			goto out;
1178*4882a593Smuzhiyun 		}
1179*4882a593Smuzhiyun 		if (key)
1180*4882a593Smuzhiyun 			keysize = (key->sadb_key_bits + 7) / 8;
1181*4882a593Smuzhiyun 		x->aalg = kmalloc(sizeof(*x->aalg) + keysize, GFP_KERNEL);
1182*4882a593Smuzhiyun 		if (!x->aalg) {
1183*4882a593Smuzhiyun 			err = -ENOMEM;
1184*4882a593Smuzhiyun 			goto out;
1185*4882a593Smuzhiyun 		}
1186*4882a593Smuzhiyun 		strcpy(x->aalg->alg_name, a->name);
1187*4882a593Smuzhiyun 		x->aalg->alg_key_len = 0;
1188*4882a593Smuzhiyun 		if (key) {
1189*4882a593Smuzhiyun 			x->aalg->alg_key_len = key->sadb_key_bits;
1190*4882a593Smuzhiyun 			memcpy(x->aalg->alg_key, key+1, keysize);
1191*4882a593Smuzhiyun 		}
1192*4882a593Smuzhiyun 		x->aalg->alg_trunc_len = a->uinfo.auth.icv_truncbits;
1193*4882a593Smuzhiyun 		x->props.aalgo = sa->sadb_sa_auth;
1194*4882a593Smuzhiyun 		/* x->algo.flags = sa->sadb_sa_flags; */
1195*4882a593Smuzhiyun 	}
1196*4882a593Smuzhiyun 	if (sa->sadb_sa_encrypt) {
1197*4882a593Smuzhiyun 		if (hdr->sadb_msg_satype == SADB_X_SATYPE_IPCOMP) {
1198*4882a593Smuzhiyun 			struct xfrm_algo_desc *a = xfrm_calg_get_byid(sa->sadb_sa_encrypt);
1199*4882a593Smuzhiyun 			if (!a || !a->pfkey_supported) {
1200*4882a593Smuzhiyun 				err = -ENOSYS;
1201*4882a593Smuzhiyun 				goto out;
1202*4882a593Smuzhiyun 			}
1203*4882a593Smuzhiyun 			x->calg = kmalloc(sizeof(*x->calg), GFP_KERNEL);
1204*4882a593Smuzhiyun 			if (!x->calg) {
1205*4882a593Smuzhiyun 				err = -ENOMEM;
1206*4882a593Smuzhiyun 				goto out;
1207*4882a593Smuzhiyun 			}
1208*4882a593Smuzhiyun 			strcpy(x->calg->alg_name, a->name);
1209*4882a593Smuzhiyun 			x->props.calgo = sa->sadb_sa_encrypt;
1210*4882a593Smuzhiyun 		} else {
1211*4882a593Smuzhiyun 			int keysize = 0;
1212*4882a593Smuzhiyun 			struct xfrm_algo_desc *a = xfrm_ealg_get_byid(sa->sadb_sa_encrypt);
1213*4882a593Smuzhiyun 			if (!a || !a->pfkey_supported) {
1214*4882a593Smuzhiyun 				err = -ENOSYS;
1215*4882a593Smuzhiyun 				goto out;
1216*4882a593Smuzhiyun 			}
1217*4882a593Smuzhiyun 			key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_ENCRYPT-1];
1218*4882a593Smuzhiyun 			if (key)
1219*4882a593Smuzhiyun 				keysize = (key->sadb_key_bits + 7) / 8;
1220*4882a593Smuzhiyun 			x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL);
1221*4882a593Smuzhiyun 			if (!x->ealg) {
1222*4882a593Smuzhiyun 				err = -ENOMEM;
1223*4882a593Smuzhiyun 				goto out;
1224*4882a593Smuzhiyun 			}
1225*4882a593Smuzhiyun 			strcpy(x->ealg->alg_name, a->name);
1226*4882a593Smuzhiyun 			x->ealg->alg_key_len = 0;
1227*4882a593Smuzhiyun 			if (key) {
1228*4882a593Smuzhiyun 				x->ealg->alg_key_len = key->sadb_key_bits;
1229*4882a593Smuzhiyun 				memcpy(x->ealg->alg_key, key+1, keysize);
1230*4882a593Smuzhiyun 			}
1231*4882a593Smuzhiyun 			x->props.ealgo = sa->sadb_sa_encrypt;
1232*4882a593Smuzhiyun 			x->geniv = a->uinfo.encr.geniv;
1233*4882a593Smuzhiyun 		}
1234*4882a593Smuzhiyun 	}
1235*4882a593Smuzhiyun 	/* x->algo.flags = sa->sadb_sa_flags; */
1236*4882a593Smuzhiyun 
1237*4882a593Smuzhiyun 	x->props.family = pfkey_sadb_addr2xfrm_addr((struct sadb_address *) ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
1238*4882a593Smuzhiyun 						    &x->props.saddr);
1239*4882a593Smuzhiyun 	pfkey_sadb_addr2xfrm_addr((struct sadb_address *) ext_hdrs[SADB_EXT_ADDRESS_DST-1],
1240*4882a593Smuzhiyun 				  &x->id.daddr);
1241*4882a593Smuzhiyun 
1242*4882a593Smuzhiyun 	if (ext_hdrs[SADB_X_EXT_SA2-1]) {
1243*4882a593Smuzhiyun 		const struct sadb_x_sa2 *sa2 = ext_hdrs[SADB_X_EXT_SA2-1];
1244*4882a593Smuzhiyun 		int mode = pfkey_mode_to_xfrm(sa2->sadb_x_sa2_mode);
1245*4882a593Smuzhiyun 		if (mode < 0) {
1246*4882a593Smuzhiyun 			err = -EINVAL;
1247*4882a593Smuzhiyun 			goto out;
1248*4882a593Smuzhiyun 		}
1249*4882a593Smuzhiyun 		x->props.mode = mode;
1250*4882a593Smuzhiyun 		x->props.reqid = sa2->sadb_x_sa2_reqid;
1251*4882a593Smuzhiyun 	}
1252*4882a593Smuzhiyun 
1253*4882a593Smuzhiyun 	if (ext_hdrs[SADB_EXT_ADDRESS_PROXY-1]) {
1254*4882a593Smuzhiyun 		const struct sadb_address *addr = ext_hdrs[SADB_EXT_ADDRESS_PROXY-1];
1255*4882a593Smuzhiyun 
1256*4882a593Smuzhiyun 		/* Nobody uses this, but we try. */
1257*4882a593Smuzhiyun 		x->sel.family = pfkey_sadb_addr2xfrm_addr(addr, &x->sel.saddr);
1258*4882a593Smuzhiyun 		x->sel.prefixlen_s = addr->sadb_address_prefixlen;
1259*4882a593Smuzhiyun 	}
1260*4882a593Smuzhiyun 
1261*4882a593Smuzhiyun 	if (!x->sel.family)
1262*4882a593Smuzhiyun 		x->sel.family = x->props.family;
1263*4882a593Smuzhiyun 
1264*4882a593Smuzhiyun 	if (ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1]) {
1265*4882a593Smuzhiyun 		const struct sadb_x_nat_t_type* n_type;
1266*4882a593Smuzhiyun 		struct xfrm_encap_tmpl *natt;
1267*4882a593Smuzhiyun 
1268*4882a593Smuzhiyun 		x->encap = kmalloc(sizeof(*x->encap), GFP_KERNEL);
1269*4882a593Smuzhiyun 		if (!x->encap) {
1270*4882a593Smuzhiyun 			err = -ENOMEM;
1271*4882a593Smuzhiyun 			goto out;
1272*4882a593Smuzhiyun 		}
1273*4882a593Smuzhiyun 
1274*4882a593Smuzhiyun 		natt = x->encap;
1275*4882a593Smuzhiyun 		n_type = ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1];
1276*4882a593Smuzhiyun 		natt->encap_type = n_type->sadb_x_nat_t_type_type;
1277*4882a593Smuzhiyun 
1278*4882a593Smuzhiyun 		if (ext_hdrs[SADB_X_EXT_NAT_T_SPORT-1]) {
1279*4882a593Smuzhiyun 			const struct sadb_x_nat_t_port *n_port =
1280*4882a593Smuzhiyun 				ext_hdrs[SADB_X_EXT_NAT_T_SPORT-1];
1281*4882a593Smuzhiyun 			natt->encap_sport = n_port->sadb_x_nat_t_port_port;
1282*4882a593Smuzhiyun 		}
1283*4882a593Smuzhiyun 		if (ext_hdrs[SADB_X_EXT_NAT_T_DPORT-1]) {
1284*4882a593Smuzhiyun 			const struct sadb_x_nat_t_port *n_port =
1285*4882a593Smuzhiyun 				ext_hdrs[SADB_X_EXT_NAT_T_DPORT-1];
1286*4882a593Smuzhiyun 			natt->encap_dport = n_port->sadb_x_nat_t_port_port;
1287*4882a593Smuzhiyun 		}
1288*4882a593Smuzhiyun 		memset(&natt->encap_oa, 0, sizeof(natt->encap_oa));
1289*4882a593Smuzhiyun 	}
1290*4882a593Smuzhiyun 
1291*4882a593Smuzhiyun 	err = xfrm_init_state(x);
1292*4882a593Smuzhiyun 	if (err)
1293*4882a593Smuzhiyun 		goto out;
1294*4882a593Smuzhiyun 
1295*4882a593Smuzhiyun 	x->km.seq = hdr->sadb_msg_seq;
1296*4882a593Smuzhiyun 	return x;
1297*4882a593Smuzhiyun 
1298*4882a593Smuzhiyun out:
1299*4882a593Smuzhiyun 	x->km.state = XFRM_STATE_DEAD;
1300*4882a593Smuzhiyun 	xfrm_state_put(x);
1301*4882a593Smuzhiyun 	return ERR_PTR(err);
1302*4882a593Smuzhiyun }
1303*4882a593Smuzhiyun 
pfkey_reserved(struct sock * sk,struct sk_buff * skb,const struct sadb_msg * hdr,void * const * ext_hdrs)1304*4882a593Smuzhiyun static int pfkey_reserved(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
1305*4882a593Smuzhiyun {
1306*4882a593Smuzhiyun 	return -EOPNOTSUPP;
1307*4882a593Smuzhiyun }
1308*4882a593Smuzhiyun 
pfkey_getspi(struct sock * sk,struct sk_buff * skb,const struct sadb_msg * hdr,void * const * ext_hdrs)1309*4882a593Smuzhiyun static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
1310*4882a593Smuzhiyun {
1311*4882a593Smuzhiyun 	struct net *net = sock_net(sk);
1312*4882a593Smuzhiyun 	struct sk_buff *resp_skb;
1313*4882a593Smuzhiyun 	struct sadb_x_sa2 *sa2;
1314*4882a593Smuzhiyun 	struct sadb_address *saddr, *daddr;
1315*4882a593Smuzhiyun 	struct sadb_msg *out_hdr;
1316*4882a593Smuzhiyun 	struct sadb_spirange *range;
1317*4882a593Smuzhiyun 	struct xfrm_state *x = NULL;
1318*4882a593Smuzhiyun 	int mode;
1319*4882a593Smuzhiyun 	int err;
1320*4882a593Smuzhiyun 	u32 min_spi, max_spi;
1321*4882a593Smuzhiyun 	u32 reqid;
1322*4882a593Smuzhiyun 	u8 proto;
1323*4882a593Smuzhiyun 	unsigned short family;
1324*4882a593Smuzhiyun 	xfrm_address_t *xsaddr = NULL, *xdaddr = NULL;
1325*4882a593Smuzhiyun 
1326*4882a593Smuzhiyun 	if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
1327*4882a593Smuzhiyun 				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]))
1328*4882a593Smuzhiyun 		return -EINVAL;
1329*4882a593Smuzhiyun 
1330*4882a593Smuzhiyun 	proto = pfkey_satype2proto(hdr->sadb_msg_satype);
1331*4882a593Smuzhiyun 	if (proto == 0)
1332*4882a593Smuzhiyun 		return -EINVAL;
1333*4882a593Smuzhiyun 
1334*4882a593Smuzhiyun 	if ((sa2 = ext_hdrs[SADB_X_EXT_SA2-1]) != NULL) {
1335*4882a593Smuzhiyun 		mode = pfkey_mode_to_xfrm(sa2->sadb_x_sa2_mode);
1336*4882a593Smuzhiyun 		if (mode < 0)
1337*4882a593Smuzhiyun 			return -EINVAL;
1338*4882a593Smuzhiyun 		reqid = sa2->sadb_x_sa2_reqid;
1339*4882a593Smuzhiyun 	} else {
1340*4882a593Smuzhiyun 		mode = 0;
1341*4882a593Smuzhiyun 		reqid = 0;
1342*4882a593Smuzhiyun 	}
1343*4882a593Smuzhiyun 
1344*4882a593Smuzhiyun 	saddr = ext_hdrs[SADB_EXT_ADDRESS_SRC-1];
1345*4882a593Smuzhiyun 	daddr = ext_hdrs[SADB_EXT_ADDRESS_DST-1];
1346*4882a593Smuzhiyun 
1347*4882a593Smuzhiyun 	family = ((struct sockaddr *)(saddr + 1))->sa_family;
1348*4882a593Smuzhiyun 	switch (family) {
1349*4882a593Smuzhiyun 	case AF_INET:
1350*4882a593Smuzhiyun 		xdaddr = (xfrm_address_t *)&((struct sockaddr_in *)(daddr + 1))->sin_addr.s_addr;
1351*4882a593Smuzhiyun 		xsaddr = (xfrm_address_t *)&((struct sockaddr_in *)(saddr + 1))->sin_addr.s_addr;
1352*4882a593Smuzhiyun 		break;
1353*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
1354*4882a593Smuzhiyun 	case AF_INET6:
1355*4882a593Smuzhiyun 		xdaddr = (xfrm_address_t *)&((struct sockaddr_in6 *)(daddr + 1))->sin6_addr;
1356*4882a593Smuzhiyun 		xsaddr = (xfrm_address_t *)&((struct sockaddr_in6 *)(saddr + 1))->sin6_addr;
1357*4882a593Smuzhiyun 		break;
1358*4882a593Smuzhiyun #endif
1359*4882a593Smuzhiyun 	}
1360*4882a593Smuzhiyun 
1361*4882a593Smuzhiyun 	if (hdr->sadb_msg_seq) {
1362*4882a593Smuzhiyun 		x = xfrm_find_acq_byseq(net, DUMMY_MARK, hdr->sadb_msg_seq);
1363*4882a593Smuzhiyun 		if (x && !xfrm_addr_equal(&x->id.daddr, xdaddr, family)) {
1364*4882a593Smuzhiyun 			xfrm_state_put(x);
1365*4882a593Smuzhiyun 			x = NULL;
1366*4882a593Smuzhiyun 		}
1367*4882a593Smuzhiyun 	}
1368*4882a593Smuzhiyun 
1369*4882a593Smuzhiyun 	if (!x)
1370*4882a593Smuzhiyun 		x = xfrm_find_acq(net, &dummy_mark, mode, reqid, 0, proto, xdaddr, xsaddr, 1, family);
1371*4882a593Smuzhiyun 
1372*4882a593Smuzhiyun 	if (x == NULL)
1373*4882a593Smuzhiyun 		return -ENOENT;
1374*4882a593Smuzhiyun 
1375*4882a593Smuzhiyun 	min_spi = 0x100;
1376*4882a593Smuzhiyun 	max_spi = 0x0fffffff;
1377*4882a593Smuzhiyun 
1378*4882a593Smuzhiyun 	range = ext_hdrs[SADB_EXT_SPIRANGE-1];
1379*4882a593Smuzhiyun 	if (range) {
1380*4882a593Smuzhiyun 		min_spi = range->sadb_spirange_min;
1381*4882a593Smuzhiyun 		max_spi = range->sadb_spirange_max;
1382*4882a593Smuzhiyun 	}
1383*4882a593Smuzhiyun 
1384*4882a593Smuzhiyun 	err = verify_spi_info(x->id.proto, min_spi, max_spi);
1385*4882a593Smuzhiyun 	if (err) {
1386*4882a593Smuzhiyun 		xfrm_state_put(x);
1387*4882a593Smuzhiyun 		return err;
1388*4882a593Smuzhiyun 	}
1389*4882a593Smuzhiyun 
1390*4882a593Smuzhiyun 	err = xfrm_alloc_spi(x, min_spi, max_spi);
1391*4882a593Smuzhiyun 	resp_skb = err ? ERR_PTR(err) : pfkey_xfrm_state2msg(x);
1392*4882a593Smuzhiyun 
1393*4882a593Smuzhiyun 	if (IS_ERR(resp_skb)) {
1394*4882a593Smuzhiyun 		xfrm_state_put(x);
1395*4882a593Smuzhiyun 		return  PTR_ERR(resp_skb);
1396*4882a593Smuzhiyun 	}
1397*4882a593Smuzhiyun 
1398*4882a593Smuzhiyun 	out_hdr = (struct sadb_msg *) resp_skb->data;
1399*4882a593Smuzhiyun 	out_hdr->sadb_msg_version = hdr->sadb_msg_version;
1400*4882a593Smuzhiyun 	out_hdr->sadb_msg_type = SADB_GETSPI;
1401*4882a593Smuzhiyun 	out_hdr->sadb_msg_satype = pfkey_proto2satype(proto);
1402*4882a593Smuzhiyun 	out_hdr->sadb_msg_errno = 0;
1403*4882a593Smuzhiyun 	out_hdr->sadb_msg_reserved = 0;
1404*4882a593Smuzhiyun 	out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
1405*4882a593Smuzhiyun 	out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
1406*4882a593Smuzhiyun 
1407*4882a593Smuzhiyun 	xfrm_state_put(x);
1408*4882a593Smuzhiyun 
1409*4882a593Smuzhiyun 	pfkey_broadcast(resp_skb, GFP_KERNEL, BROADCAST_ONE, sk, net);
1410*4882a593Smuzhiyun 
1411*4882a593Smuzhiyun 	return 0;
1412*4882a593Smuzhiyun }
1413*4882a593Smuzhiyun 
pfkey_acquire(struct sock * sk,struct sk_buff * skb,const struct sadb_msg * hdr,void * const * ext_hdrs)1414*4882a593Smuzhiyun static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
1415*4882a593Smuzhiyun {
1416*4882a593Smuzhiyun 	struct net *net = sock_net(sk);
1417*4882a593Smuzhiyun 	struct xfrm_state *x;
1418*4882a593Smuzhiyun 
1419*4882a593Smuzhiyun 	if (hdr->sadb_msg_len != sizeof(struct sadb_msg)/8)
1420*4882a593Smuzhiyun 		return -EOPNOTSUPP;
1421*4882a593Smuzhiyun 
1422*4882a593Smuzhiyun 	if (hdr->sadb_msg_seq == 0 || hdr->sadb_msg_errno == 0)
1423*4882a593Smuzhiyun 		return 0;
1424*4882a593Smuzhiyun 
1425*4882a593Smuzhiyun 	x = xfrm_find_acq_byseq(net, DUMMY_MARK, hdr->sadb_msg_seq);
1426*4882a593Smuzhiyun 	if (x == NULL)
1427*4882a593Smuzhiyun 		return 0;
1428*4882a593Smuzhiyun 
1429*4882a593Smuzhiyun 	spin_lock_bh(&x->lock);
1430*4882a593Smuzhiyun 	if (x->km.state == XFRM_STATE_ACQ)
1431*4882a593Smuzhiyun 		x->km.state = XFRM_STATE_ERROR;
1432*4882a593Smuzhiyun 
1433*4882a593Smuzhiyun 	spin_unlock_bh(&x->lock);
1434*4882a593Smuzhiyun 	xfrm_state_put(x);
1435*4882a593Smuzhiyun 	return 0;
1436*4882a593Smuzhiyun }
1437*4882a593Smuzhiyun 
event2poltype(int event)1438*4882a593Smuzhiyun static inline int event2poltype(int event)
1439*4882a593Smuzhiyun {
1440*4882a593Smuzhiyun 	switch (event) {
1441*4882a593Smuzhiyun 	case XFRM_MSG_DELPOLICY:
1442*4882a593Smuzhiyun 		return SADB_X_SPDDELETE;
1443*4882a593Smuzhiyun 	case XFRM_MSG_NEWPOLICY:
1444*4882a593Smuzhiyun 		return SADB_X_SPDADD;
1445*4882a593Smuzhiyun 	case XFRM_MSG_UPDPOLICY:
1446*4882a593Smuzhiyun 		return SADB_X_SPDUPDATE;
1447*4882a593Smuzhiyun 	case XFRM_MSG_POLEXPIRE:
1448*4882a593Smuzhiyun 	//	return SADB_X_SPDEXPIRE;
1449*4882a593Smuzhiyun 	default:
1450*4882a593Smuzhiyun 		pr_err("pfkey: Unknown policy event %d\n", event);
1451*4882a593Smuzhiyun 		break;
1452*4882a593Smuzhiyun 	}
1453*4882a593Smuzhiyun 
1454*4882a593Smuzhiyun 	return 0;
1455*4882a593Smuzhiyun }
1456*4882a593Smuzhiyun 
event2keytype(int event)1457*4882a593Smuzhiyun static inline int event2keytype(int event)
1458*4882a593Smuzhiyun {
1459*4882a593Smuzhiyun 	switch (event) {
1460*4882a593Smuzhiyun 	case XFRM_MSG_DELSA:
1461*4882a593Smuzhiyun 		return SADB_DELETE;
1462*4882a593Smuzhiyun 	case XFRM_MSG_NEWSA:
1463*4882a593Smuzhiyun 		return SADB_ADD;
1464*4882a593Smuzhiyun 	case XFRM_MSG_UPDSA:
1465*4882a593Smuzhiyun 		return SADB_UPDATE;
1466*4882a593Smuzhiyun 	case XFRM_MSG_EXPIRE:
1467*4882a593Smuzhiyun 		return SADB_EXPIRE;
1468*4882a593Smuzhiyun 	default:
1469*4882a593Smuzhiyun 		pr_err("pfkey: Unknown SA event %d\n", event);
1470*4882a593Smuzhiyun 		break;
1471*4882a593Smuzhiyun 	}
1472*4882a593Smuzhiyun 
1473*4882a593Smuzhiyun 	return 0;
1474*4882a593Smuzhiyun }
1475*4882a593Smuzhiyun 
1476*4882a593Smuzhiyun /* ADD/UPD/DEL */
key_notify_sa(struct xfrm_state * x,const struct km_event * c)1477*4882a593Smuzhiyun static int key_notify_sa(struct xfrm_state *x, const struct km_event *c)
1478*4882a593Smuzhiyun {
1479*4882a593Smuzhiyun 	struct sk_buff *skb;
1480*4882a593Smuzhiyun 	struct sadb_msg *hdr;
1481*4882a593Smuzhiyun 
1482*4882a593Smuzhiyun 	skb = pfkey_xfrm_state2msg(x);
1483*4882a593Smuzhiyun 
1484*4882a593Smuzhiyun 	if (IS_ERR(skb))
1485*4882a593Smuzhiyun 		return PTR_ERR(skb);
1486*4882a593Smuzhiyun 
1487*4882a593Smuzhiyun 	hdr = (struct sadb_msg *) skb->data;
1488*4882a593Smuzhiyun 	hdr->sadb_msg_version = PF_KEY_V2;
1489*4882a593Smuzhiyun 	hdr->sadb_msg_type = event2keytype(c->event);
1490*4882a593Smuzhiyun 	hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto);
1491*4882a593Smuzhiyun 	hdr->sadb_msg_errno = 0;
1492*4882a593Smuzhiyun 	hdr->sadb_msg_reserved = 0;
1493*4882a593Smuzhiyun 	hdr->sadb_msg_seq = c->seq;
1494*4882a593Smuzhiyun 	hdr->sadb_msg_pid = c->portid;
1495*4882a593Smuzhiyun 
1496*4882a593Smuzhiyun 	pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, xs_net(x));
1497*4882a593Smuzhiyun 
1498*4882a593Smuzhiyun 	return 0;
1499*4882a593Smuzhiyun }
1500*4882a593Smuzhiyun 
pfkey_add(struct sock * sk,struct sk_buff * skb,const struct sadb_msg * hdr,void * const * ext_hdrs)1501*4882a593Smuzhiyun static int pfkey_add(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
1502*4882a593Smuzhiyun {
1503*4882a593Smuzhiyun 	struct net *net = sock_net(sk);
1504*4882a593Smuzhiyun 	struct xfrm_state *x;
1505*4882a593Smuzhiyun 	int err;
1506*4882a593Smuzhiyun 	struct km_event c;
1507*4882a593Smuzhiyun 
1508*4882a593Smuzhiyun 	x = pfkey_msg2xfrm_state(net, hdr, ext_hdrs);
1509*4882a593Smuzhiyun 	if (IS_ERR(x))
1510*4882a593Smuzhiyun 		return PTR_ERR(x);
1511*4882a593Smuzhiyun 
1512*4882a593Smuzhiyun 	xfrm_state_hold(x);
1513*4882a593Smuzhiyun 	if (hdr->sadb_msg_type == SADB_ADD)
1514*4882a593Smuzhiyun 		err = xfrm_state_add(x);
1515*4882a593Smuzhiyun 	else
1516*4882a593Smuzhiyun 		err = xfrm_state_update(x);
1517*4882a593Smuzhiyun 
1518*4882a593Smuzhiyun 	xfrm_audit_state_add(x, err ? 0 : 1, true);
1519*4882a593Smuzhiyun 
1520*4882a593Smuzhiyun 	if (err < 0) {
1521*4882a593Smuzhiyun 		x->km.state = XFRM_STATE_DEAD;
1522*4882a593Smuzhiyun 		__xfrm_state_put(x);
1523*4882a593Smuzhiyun 		goto out;
1524*4882a593Smuzhiyun 	}
1525*4882a593Smuzhiyun 
1526*4882a593Smuzhiyun 	if (hdr->sadb_msg_type == SADB_ADD)
1527*4882a593Smuzhiyun 		c.event = XFRM_MSG_NEWSA;
1528*4882a593Smuzhiyun 	else
1529*4882a593Smuzhiyun 		c.event = XFRM_MSG_UPDSA;
1530*4882a593Smuzhiyun 	c.seq = hdr->sadb_msg_seq;
1531*4882a593Smuzhiyun 	c.portid = hdr->sadb_msg_pid;
1532*4882a593Smuzhiyun 	km_state_notify(x, &c);
1533*4882a593Smuzhiyun out:
1534*4882a593Smuzhiyun 	xfrm_state_put(x);
1535*4882a593Smuzhiyun 	return err;
1536*4882a593Smuzhiyun }
1537*4882a593Smuzhiyun 
pfkey_delete(struct sock * sk,struct sk_buff * skb,const struct sadb_msg * hdr,void * const * ext_hdrs)1538*4882a593Smuzhiyun static int pfkey_delete(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
1539*4882a593Smuzhiyun {
1540*4882a593Smuzhiyun 	struct net *net = sock_net(sk);
1541*4882a593Smuzhiyun 	struct xfrm_state *x;
1542*4882a593Smuzhiyun 	struct km_event c;
1543*4882a593Smuzhiyun 	int err;
1544*4882a593Smuzhiyun 
1545*4882a593Smuzhiyun 	if (!ext_hdrs[SADB_EXT_SA-1] ||
1546*4882a593Smuzhiyun 	    !present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
1547*4882a593Smuzhiyun 				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]))
1548*4882a593Smuzhiyun 		return -EINVAL;
1549*4882a593Smuzhiyun 
1550*4882a593Smuzhiyun 	x = pfkey_xfrm_state_lookup(net, hdr, ext_hdrs);
1551*4882a593Smuzhiyun 	if (x == NULL)
1552*4882a593Smuzhiyun 		return -ESRCH;
1553*4882a593Smuzhiyun 
1554*4882a593Smuzhiyun 	if ((err = security_xfrm_state_delete(x)))
1555*4882a593Smuzhiyun 		goto out;
1556*4882a593Smuzhiyun 
1557*4882a593Smuzhiyun 	if (xfrm_state_kern(x)) {
1558*4882a593Smuzhiyun 		err = -EPERM;
1559*4882a593Smuzhiyun 		goto out;
1560*4882a593Smuzhiyun 	}
1561*4882a593Smuzhiyun 
1562*4882a593Smuzhiyun 	err = xfrm_state_delete(x);
1563*4882a593Smuzhiyun 
1564*4882a593Smuzhiyun 	if (err < 0)
1565*4882a593Smuzhiyun 		goto out;
1566*4882a593Smuzhiyun 
1567*4882a593Smuzhiyun 	c.seq = hdr->sadb_msg_seq;
1568*4882a593Smuzhiyun 	c.portid = hdr->sadb_msg_pid;
1569*4882a593Smuzhiyun 	c.event = XFRM_MSG_DELSA;
1570*4882a593Smuzhiyun 	km_state_notify(x, &c);
1571*4882a593Smuzhiyun out:
1572*4882a593Smuzhiyun 	xfrm_audit_state_delete(x, err ? 0 : 1, true);
1573*4882a593Smuzhiyun 	xfrm_state_put(x);
1574*4882a593Smuzhiyun 
1575*4882a593Smuzhiyun 	return err;
1576*4882a593Smuzhiyun }
1577*4882a593Smuzhiyun 
pfkey_get(struct sock * sk,struct sk_buff * skb,const struct sadb_msg * hdr,void * const * ext_hdrs)1578*4882a593Smuzhiyun static int pfkey_get(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
1579*4882a593Smuzhiyun {
1580*4882a593Smuzhiyun 	struct net *net = sock_net(sk);
1581*4882a593Smuzhiyun 	__u8 proto;
1582*4882a593Smuzhiyun 	struct sk_buff *out_skb;
1583*4882a593Smuzhiyun 	struct sadb_msg *out_hdr;
1584*4882a593Smuzhiyun 	struct xfrm_state *x;
1585*4882a593Smuzhiyun 
1586*4882a593Smuzhiyun 	if (!ext_hdrs[SADB_EXT_SA-1] ||
1587*4882a593Smuzhiyun 	    !present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
1588*4882a593Smuzhiyun 				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]))
1589*4882a593Smuzhiyun 		return -EINVAL;
1590*4882a593Smuzhiyun 
1591*4882a593Smuzhiyun 	x = pfkey_xfrm_state_lookup(net, hdr, ext_hdrs);
1592*4882a593Smuzhiyun 	if (x == NULL)
1593*4882a593Smuzhiyun 		return -ESRCH;
1594*4882a593Smuzhiyun 
1595*4882a593Smuzhiyun 	out_skb = pfkey_xfrm_state2msg(x);
1596*4882a593Smuzhiyun 	proto = x->id.proto;
1597*4882a593Smuzhiyun 	xfrm_state_put(x);
1598*4882a593Smuzhiyun 	if (IS_ERR(out_skb))
1599*4882a593Smuzhiyun 		return  PTR_ERR(out_skb);
1600*4882a593Smuzhiyun 
1601*4882a593Smuzhiyun 	out_hdr = (struct sadb_msg *) out_skb->data;
1602*4882a593Smuzhiyun 	out_hdr->sadb_msg_version = hdr->sadb_msg_version;
1603*4882a593Smuzhiyun 	out_hdr->sadb_msg_type = SADB_GET;
1604*4882a593Smuzhiyun 	out_hdr->sadb_msg_satype = pfkey_proto2satype(proto);
1605*4882a593Smuzhiyun 	out_hdr->sadb_msg_errno = 0;
1606*4882a593Smuzhiyun 	out_hdr->sadb_msg_reserved = 0;
1607*4882a593Smuzhiyun 	out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
1608*4882a593Smuzhiyun 	out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
1609*4882a593Smuzhiyun 	pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk, sock_net(sk));
1610*4882a593Smuzhiyun 
1611*4882a593Smuzhiyun 	return 0;
1612*4882a593Smuzhiyun }
1613*4882a593Smuzhiyun 
compose_sadb_supported(const struct sadb_msg * orig,gfp_t allocation)1614*4882a593Smuzhiyun static struct sk_buff *compose_sadb_supported(const struct sadb_msg *orig,
1615*4882a593Smuzhiyun 					      gfp_t allocation)
1616*4882a593Smuzhiyun {
1617*4882a593Smuzhiyun 	struct sk_buff *skb;
1618*4882a593Smuzhiyun 	struct sadb_msg *hdr;
1619*4882a593Smuzhiyun 	int len, auth_len, enc_len, i;
1620*4882a593Smuzhiyun 
1621*4882a593Smuzhiyun 	auth_len = xfrm_count_pfkey_auth_supported();
1622*4882a593Smuzhiyun 	if (auth_len) {
1623*4882a593Smuzhiyun 		auth_len *= sizeof(struct sadb_alg);
1624*4882a593Smuzhiyun 		auth_len += sizeof(struct sadb_supported);
1625*4882a593Smuzhiyun 	}
1626*4882a593Smuzhiyun 
1627*4882a593Smuzhiyun 	enc_len = xfrm_count_pfkey_enc_supported();
1628*4882a593Smuzhiyun 	if (enc_len) {
1629*4882a593Smuzhiyun 		enc_len *= sizeof(struct sadb_alg);
1630*4882a593Smuzhiyun 		enc_len += sizeof(struct sadb_supported);
1631*4882a593Smuzhiyun 	}
1632*4882a593Smuzhiyun 
1633*4882a593Smuzhiyun 	len = enc_len + auth_len + sizeof(struct sadb_msg);
1634*4882a593Smuzhiyun 
1635*4882a593Smuzhiyun 	skb = alloc_skb(len + 16, allocation);
1636*4882a593Smuzhiyun 	if (!skb)
1637*4882a593Smuzhiyun 		goto out_put_algs;
1638*4882a593Smuzhiyun 
1639*4882a593Smuzhiyun 	hdr = skb_put(skb, sizeof(*hdr));
1640*4882a593Smuzhiyun 	pfkey_hdr_dup(hdr, orig);
1641*4882a593Smuzhiyun 	hdr->sadb_msg_errno = 0;
1642*4882a593Smuzhiyun 	hdr->sadb_msg_len = len / sizeof(uint64_t);
1643*4882a593Smuzhiyun 
1644*4882a593Smuzhiyun 	if (auth_len) {
1645*4882a593Smuzhiyun 		struct sadb_supported *sp;
1646*4882a593Smuzhiyun 		struct sadb_alg *ap;
1647*4882a593Smuzhiyun 
1648*4882a593Smuzhiyun 		sp = skb_put(skb, auth_len);
1649*4882a593Smuzhiyun 		ap = (struct sadb_alg *) (sp + 1);
1650*4882a593Smuzhiyun 
1651*4882a593Smuzhiyun 		sp->sadb_supported_len = auth_len / sizeof(uint64_t);
1652*4882a593Smuzhiyun 		sp->sadb_supported_exttype = SADB_EXT_SUPPORTED_AUTH;
1653*4882a593Smuzhiyun 
1654*4882a593Smuzhiyun 		for (i = 0; ; i++) {
1655*4882a593Smuzhiyun 			struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(i);
1656*4882a593Smuzhiyun 			if (!aalg)
1657*4882a593Smuzhiyun 				break;
1658*4882a593Smuzhiyun 			if (!aalg->pfkey_supported)
1659*4882a593Smuzhiyun 				continue;
1660*4882a593Smuzhiyun 			if (aalg->available)
1661*4882a593Smuzhiyun 				*ap++ = aalg->desc;
1662*4882a593Smuzhiyun 		}
1663*4882a593Smuzhiyun 	}
1664*4882a593Smuzhiyun 
1665*4882a593Smuzhiyun 	if (enc_len) {
1666*4882a593Smuzhiyun 		struct sadb_supported *sp;
1667*4882a593Smuzhiyun 		struct sadb_alg *ap;
1668*4882a593Smuzhiyun 
1669*4882a593Smuzhiyun 		sp = skb_put(skb, enc_len);
1670*4882a593Smuzhiyun 		ap = (struct sadb_alg *) (sp + 1);
1671*4882a593Smuzhiyun 
1672*4882a593Smuzhiyun 		sp->sadb_supported_len = enc_len / sizeof(uint64_t);
1673*4882a593Smuzhiyun 		sp->sadb_supported_exttype = SADB_EXT_SUPPORTED_ENCRYPT;
1674*4882a593Smuzhiyun 
1675*4882a593Smuzhiyun 		for (i = 0; ; i++) {
1676*4882a593Smuzhiyun 			struct xfrm_algo_desc *ealg = xfrm_ealg_get_byidx(i);
1677*4882a593Smuzhiyun 			if (!ealg)
1678*4882a593Smuzhiyun 				break;
1679*4882a593Smuzhiyun 			if (!ealg->pfkey_supported)
1680*4882a593Smuzhiyun 				continue;
1681*4882a593Smuzhiyun 			if (ealg->available)
1682*4882a593Smuzhiyun 				*ap++ = ealg->desc;
1683*4882a593Smuzhiyun 		}
1684*4882a593Smuzhiyun 	}
1685*4882a593Smuzhiyun 
1686*4882a593Smuzhiyun out_put_algs:
1687*4882a593Smuzhiyun 	return skb;
1688*4882a593Smuzhiyun }
1689*4882a593Smuzhiyun 
pfkey_register(struct sock * sk,struct sk_buff * skb,const struct sadb_msg * hdr,void * const * ext_hdrs)1690*4882a593Smuzhiyun static int pfkey_register(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
1691*4882a593Smuzhiyun {
1692*4882a593Smuzhiyun 	struct pfkey_sock *pfk = pfkey_sk(sk);
1693*4882a593Smuzhiyun 	struct sk_buff *supp_skb;
1694*4882a593Smuzhiyun 
1695*4882a593Smuzhiyun 	if (hdr->sadb_msg_satype > SADB_SATYPE_MAX)
1696*4882a593Smuzhiyun 		return -EINVAL;
1697*4882a593Smuzhiyun 
1698*4882a593Smuzhiyun 	if (hdr->sadb_msg_satype != SADB_SATYPE_UNSPEC) {
1699*4882a593Smuzhiyun 		if (pfk->registered&(1<<hdr->sadb_msg_satype))
1700*4882a593Smuzhiyun 			return -EEXIST;
1701*4882a593Smuzhiyun 		pfk->registered |= (1<<hdr->sadb_msg_satype);
1702*4882a593Smuzhiyun 	}
1703*4882a593Smuzhiyun 
1704*4882a593Smuzhiyun 	mutex_lock(&pfkey_mutex);
1705*4882a593Smuzhiyun 	xfrm_probe_algs();
1706*4882a593Smuzhiyun 
1707*4882a593Smuzhiyun 	supp_skb = compose_sadb_supported(hdr, GFP_KERNEL | __GFP_ZERO);
1708*4882a593Smuzhiyun 	mutex_unlock(&pfkey_mutex);
1709*4882a593Smuzhiyun 
1710*4882a593Smuzhiyun 	if (!supp_skb) {
1711*4882a593Smuzhiyun 		if (hdr->sadb_msg_satype != SADB_SATYPE_UNSPEC)
1712*4882a593Smuzhiyun 			pfk->registered &= ~(1<<hdr->sadb_msg_satype);
1713*4882a593Smuzhiyun 
1714*4882a593Smuzhiyun 		return -ENOBUFS;
1715*4882a593Smuzhiyun 	}
1716*4882a593Smuzhiyun 
1717*4882a593Smuzhiyun 	pfkey_broadcast(supp_skb, GFP_KERNEL, BROADCAST_REGISTERED, sk,
1718*4882a593Smuzhiyun 			sock_net(sk));
1719*4882a593Smuzhiyun 	return 0;
1720*4882a593Smuzhiyun }
1721*4882a593Smuzhiyun 
unicast_flush_resp(struct sock * sk,const struct sadb_msg * ihdr)1722*4882a593Smuzhiyun static int unicast_flush_resp(struct sock *sk, const struct sadb_msg *ihdr)
1723*4882a593Smuzhiyun {
1724*4882a593Smuzhiyun 	struct sk_buff *skb;
1725*4882a593Smuzhiyun 	struct sadb_msg *hdr;
1726*4882a593Smuzhiyun 
1727*4882a593Smuzhiyun 	skb = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_ATOMIC);
1728*4882a593Smuzhiyun 	if (!skb)
1729*4882a593Smuzhiyun 		return -ENOBUFS;
1730*4882a593Smuzhiyun 
1731*4882a593Smuzhiyun 	hdr = skb_put_data(skb, ihdr, sizeof(struct sadb_msg));
1732*4882a593Smuzhiyun 	hdr->sadb_msg_errno = (uint8_t) 0;
1733*4882a593Smuzhiyun 	hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
1734*4882a593Smuzhiyun 
1735*4882a593Smuzhiyun 	return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ONE, sk,
1736*4882a593Smuzhiyun 			       sock_net(sk));
1737*4882a593Smuzhiyun }
1738*4882a593Smuzhiyun 
key_notify_sa_flush(const struct km_event * c)1739*4882a593Smuzhiyun static int key_notify_sa_flush(const struct km_event *c)
1740*4882a593Smuzhiyun {
1741*4882a593Smuzhiyun 	struct sk_buff *skb;
1742*4882a593Smuzhiyun 	struct sadb_msg *hdr;
1743*4882a593Smuzhiyun 
1744*4882a593Smuzhiyun 	skb = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_ATOMIC);
1745*4882a593Smuzhiyun 	if (!skb)
1746*4882a593Smuzhiyun 		return -ENOBUFS;
1747*4882a593Smuzhiyun 	hdr = skb_put(skb, sizeof(struct sadb_msg));
1748*4882a593Smuzhiyun 	hdr->sadb_msg_satype = pfkey_proto2satype(c->data.proto);
1749*4882a593Smuzhiyun 	hdr->sadb_msg_type = SADB_FLUSH;
1750*4882a593Smuzhiyun 	hdr->sadb_msg_seq = c->seq;
1751*4882a593Smuzhiyun 	hdr->sadb_msg_pid = c->portid;
1752*4882a593Smuzhiyun 	hdr->sadb_msg_version = PF_KEY_V2;
1753*4882a593Smuzhiyun 	hdr->sadb_msg_errno = (uint8_t) 0;
1754*4882a593Smuzhiyun 	hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
1755*4882a593Smuzhiyun 	hdr->sadb_msg_reserved = 0;
1756*4882a593Smuzhiyun 
1757*4882a593Smuzhiyun 	pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net);
1758*4882a593Smuzhiyun 
1759*4882a593Smuzhiyun 	return 0;
1760*4882a593Smuzhiyun }
1761*4882a593Smuzhiyun 
pfkey_flush(struct sock * sk,struct sk_buff * skb,const struct sadb_msg * hdr,void * const * ext_hdrs)1762*4882a593Smuzhiyun static int pfkey_flush(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
1763*4882a593Smuzhiyun {
1764*4882a593Smuzhiyun 	struct net *net = sock_net(sk);
1765*4882a593Smuzhiyun 	unsigned int proto;
1766*4882a593Smuzhiyun 	struct km_event c;
1767*4882a593Smuzhiyun 	int err, err2;
1768*4882a593Smuzhiyun 
1769*4882a593Smuzhiyun 	proto = pfkey_satype2proto(hdr->sadb_msg_satype);
1770*4882a593Smuzhiyun 	if (proto == 0)
1771*4882a593Smuzhiyun 		return -EINVAL;
1772*4882a593Smuzhiyun 
1773*4882a593Smuzhiyun 	err = xfrm_state_flush(net, proto, true, false);
1774*4882a593Smuzhiyun 	err2 = unicast_flush_resp(sk, hdr);
1775*4882a593Smuzhiyun 	if (err || err2) {
1776*4882a593Smuzhiyun 		if (err == -ESRCH) /* empty table - go quietly */
1777*4882a593Smuzhiyun 			err = 0;
1778*4882a593Smuzhiyun 		return err ? err : err2;
1779*4882a593Smuzhiyun 	}
1780*4882a593Smuzhiyun 
1781*4882a593Smuzhiyun 	c.data.proto = proto;
1782*4882a593Smuzhiyun 	c.seq = hdr->sadb_msg_seq;
1783*4882a593Smuzhiyun 	c.portid = hdr->sadb_msg_pid;
1784*4882a593Smuzhiyun 	c.event = XFRM_MSG_FLUSHSA;
1785*4882a593Smuzhiyun 	c.net = net;
1786*4882a593Smuzhiyun 	km_state_notify(NULL, &c);
1787*4882a593Smuzhiyun 
1788*4882a593Smuzhiyun 	return 0;
1789*4882a593Smuzhiyun }
1790*4882a593Smuzhiyun 
dump_sa(struct xfrm_state * x,int count,void * ptr)1791*4882a593Smuzhiyun static int dump_sa(struct xfrm_state *x, int count, void *ptr)
1792*4882a593Smuzhiyun {
1793*4882a593Smuzhiyun 	struct pfkey_sock *pfk = ptr;
1794*4882a593Smuzhiyun 	struct sk_buff *out_skb;
1795*4882a593Smuzhiyun 	struct sadb_msg *out_hdr;
1796*4882a593Smuzhiyun 
1797*4882a593Smuzhiyun 	if (!pfkey_can_dump(&pfk->sk))
1798*4882a593Smuzhiyun 		return -ENOBUFS;
1799*4882a593Smuzhiyun 
1800*4882a593Smuzhiyun 	out_skb = pfkey_xfrm_state2msg(x);
1801*4882a593Smuzhiyun 	if (IS_ERR(out_skb))
1802*4882a593Smuzhiyun 		return PTR_ERR(out_skb);
1803*4882a593Smuzhiyun 
1804*4882a593Smuzhiyun 	out_hdr = (struct sadb_msg *) out_skb->data;
1805*4882a593Smuzhiyun 	out_hdr->sadb_msg_version = pfk->dump.msg_version;
1806*4882a593Smuzhiyun 	out_hdr->sadb_msg_type = SADB_DUMP;
1807*4882a593Smuzhiyun 	out_hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto);
1808*4882a593Smuzhiyun 	out_hdr->sadb_msg_errno = 0;
1809*4882a593Smuzhiyun 	out_hdr->sadb_msg_reserved = 0;
1810*4882a593Smuzhiyun 	out_hdr->sadb_msg_seq = count + 1;
1811*4882a593Smuzhiyun 	out_hdr->sadb_msg_pid = pfk->dump.msg_portid;
1812*4882a593Smuzhiyun 
1813*4882a593Smuzhiyun 	if (pfk->dump.skb)
1814*4882a593Smuzhiyun 		pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
1815*4882a593Smuzhiyun 				&pfk->sk, sock_net(&pfk->sk));
1816*4882a593Smuzhiyun 	pfk->dump.skb = out_skb;
1817*4882a593Smuzhiyun 
1818*4882a593Smuzhiyun 	return 0;
1819*4882a593Smuzhiyun }
1820*4882a593Smuzhiyun 
pfkey_dump_sa(struct pfkey_sock * pfk)1821*4882a593Smuzhiyun static int pfkey_dump_sa(struct pfkey_sock *pfk)
1822*4882a593Smuzhiyun {
1823*4882a593Smuzhiyun 	struct net *net = sock_net(&pfk->sk);
1824*4882a593Smuzhiyun 	return xfrm_state_walk(net, &pfk->dump.u.state, dump_sa, (void *) pfk);
1825*4882a593Smuzhiyun }
1826*4882a593Smuzhiyun 
pfkey_dump_sa_done(struct pfkey_sock * pfk)1827*4882a593Smuzhiyun static void pfkey_dump_sa_done(struct pfkey_sock *pfk)
1828*4882a593Smuzhiyun {
1829*4882a593Smuzhiyun 	struct net *net = sock_net(&pfk->sk);
1830*4882a593Smuzhiyun 
1831*4882a593Smuzhiyun 	xfrm_state_walk_done(&pfk->dump.u.state, net);
1832*4882a593Smuzhiyun }
1833*4882a593Smuzhiyun 
pfkey_dump(struct sock * sk,struct sk_buff * skb,const struct sadb_msg * hdr,void * const * ext_hdrs)1834*4882a593Smuzhiyun static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
1835*4882a593Smuzhiyun {
1836*4882a593Smuzhiyun 	u8 proto;
1837*4882a593Smuzhiyun 	struct xfrm_address_filter *filter = NULL;
1838*4882a593Smuzhiyun 	struct pfkey_sock *pfk = pfkey_sk(sk);
1839*4882a593Smuzhiyun 
1840*4882a593Smuzhiyun 	mutex_lock(&pfk->dump_lock);
1841*4882a593Smuzhiyun 	if (pfk->dump.dump != NULL) {
1842*4882a593Smuzhiyun 		mutex_unlock(&pfk->dump_lock);
1843*4882a593Smuzhiyun 		return -EBUSY;
1844*4882a593Smuzhiyun 	}
1845*4882a593Smuzhiyun 
1846*4882a593Smuzhiyun 	proto = pfkey_satype2proto(hdr->sadb_msg_satype);
1847*4882a593Smuzhiyun 	if (proto == 0) {
1848*4882a593Smuzhiyun 		mutex_unlock(&pfk->dump_lock);
1849*4882a593Smuzhiyun 		return -EINVAL;
1850*4882a593Smuzhiyun 	}
1851*4882a593Smuzhiyun 
1852*4882a593Smuzhiyun 	if (ext_hdrs[SADB_X_EXT_FILTER - 1]) {
1853*4882a593Smuzhiyun 		struct sadb_x_filter *xfilter = ext_hdrs[SADB_X_EXT_FILTER - 1];
1854*4882a593Smuzhiyun 
1855*4882a593Smuzhiyun 		if ((xfilter->sadb_x_filter_splen >=
1856*4882a593Smuzhiyun 			(sizeof(xfrm_address_t) << 3)) ||
1857*4882a593Smuzhiyun 		    (xfilter->sadb_x_filter_dplen >=
1858*4882a593Smuzhiyun 			(sizeof(xfrm_address_t) << 3))) {
1859*4882a593Smuzhiyun 			mutex_unlock(&pfk->dump_lock);
1860*4882a593Smuzhiyun 			return -EINVAL;
1861*4882a593Smuzhiyun 		}
1862*4882a593Smuzhiyun 		filter = kmalloc(sizeof(*filter), GFP_KERNEL);
1863*4882a593Smuzhiyun 		if (filter == NULL) {
1864*4882a593Smuzhiyun 			mutex_unlock(&pfk->dump_lock);
1865*4882a593Smuzhiyun 			return -ENOMEM;
1866*4882a593Smuzhiyun 		}
1867*4882a593Smuzhiyun 
1868*4882a593Smuzhiyun 		memcpy(&filter->saddr, &xfilter->sadb_x_filter_saddr,
1869*4882a593Smuzhiyun 		       sizeof(xfrm_address_t));
1870*4882a593Smuzhiyun 		memcpy(&filter->daddr, &xfilter->sadb_x_filter_daddr,
1871*4882a593Smuzhiyun 		       sizeof(xfrm_address_t));
1872*4882a593Smuzhiyun 		filter->family = xfilter->sadb_x_filter_family;
1873*4882a593Smuzhiyun 		filter->splen = xfilter->sadb_x_filter_splen;
1874*4882a593Smuzhiyun 		filter->dplen = xfilter->sadb_x_filter_dplen;
1875*4882a593Smuzhiyun 	}
1876*4882a593Smuzhiyun 
1877*4882a593Smuzhiyun 	pfk->dump.msg_version = hdr->sadb_msg_version;
1878*4882a593Smuzhiyun 	pfk->dump.msg_portid = hdr->sadb_msg_pid;
1879*4882a593Smuzhiyun 	pfk->dump.dump = pfkey_dump_sa;
1880*4882a593Smuzhiyun 	pfk->dump.done = pfkey_dump_sa_done;
1881*4882a593Smuzhiyun 	xfrm_state_walk_init(&pfk->dump.u.state, proto, filter);
1882*4882a593Smuzhiyun 	mutex_unlock(&pfk->dump_lock);
1883*4882a593Smuzhiyun 
1884*4882a593Smuzhiyun 	return pfkey_do_dump(pfk);
1885*4882a593Smuzhiyun }
1886*4882a593Smuzhiyun 
pfkey_promisc(struct sock * sk,struct sk_buff * skb,const struct sadb_msg * hdr,void * const * ext_hdrs)1887*4882a593Smuzhiyun static int pfkey_promisc(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
1888*4882a593Smuzhiyun {
1889*4882a593Smuzhiyun 	struct pfkey_sock *pfk = pfkey_sk(sk);
1890*4882a593Smuzhiyun 	int satype = hdr->sadb_msg_satype;
1891*4882a593Smuzhiyun 	bool reset_errno = false;
1892*4882a593Smuzhiyun 
1893*4882a593Smuzhiyun 	if (hdr->sadb_msg_len == (sizeof(*hdr) / sizeof(uint64_t))) {
1894*4882a593Smuzhiyun 		reset_errno = true;
1895*4882a593Smuzhiyun 		if (satype != 0 && satype != 1)
1896*4882a593Smuzhiyun 			return -EINVAL;
1897*4882a593Smuzhiyun 		pfk->promisc = satype;
1898*4882a593Smuzhiyun 	}
1899*4882a593Smuzhiyun 	if (reset_errno && skb_cloned(skb))
1900*4882a593Smuzhiyun 		skb = skb_copy(skb, GFP_KERNEL);
1901*4882a593Smuzhiyun 	else
1902*4882a593Smuzhiyun 		skb = skb_clone(skb, GFP_KERNEL);
1903*4882a593Smuzhiyun 
1904*4882a593Smuzhiyun 	if (reset_errno && skb) {
1905*4882a593Smuzhiyun 		struct sadb_msg *new_hdr = (struct sadb_msg *) skb->data;
1906*4882a593Smuzhiyun 		new_hdr->sadb_msg_errno = 0;
1907*4882a593Smuzhiyun 	}
1908*4882a593Smuzhiyun 
1909*4882a593Smuzhiyun 	pfkey_broadcast(skb, GFP_KERNEL, BROADCAST_ALL, NULL, sock_net(sk));
1910*4882a593Smuzhiyun 	return 0;
1911*4882a593Smuzhiyun }
1912*4882a593Smuzhiyun 
check_reqid(struct xfrm_policy * xp,int dir,int count,void * ptr)1913*4882a593Smuzhiyun static int check_reqid(struct xfrm_policy *xp, int dir, int count, void *ptr)
1914*4882a593Smuzhiyun {
1915*4882a593Smuzhiyun 	int i;
1916*4882a593Smuzhiyun 	u32 reqid = *(u32*)ptr;
1917*4882a593Smuzhiyun 
1918*4882a593Smuzhiyun 	for (i=0; i<xp->xfrm_nr; i++) {
1919*4882a593Smuzhiyun 		if (xp->xfrm_vec[i].reqid == reqid)
1920*4882a593Smuzhiyun 			return -EEXIST;
1921*4882a593Smuzhiyun 	}
1922*4882a593Smuzhiyun 	return 0;
1923*4882a593Smuzhiyun }
1924*4882a593Smuzhiyun 
gen_reqid(struct net * net)1925*4882a593Smuzhiyun static u32 gen_reqid(struct net *net)
1926*4882a593Smuzhiyun {
1927*4882a593Smuzhiyun 	struct xfrm_policy_walk walk;
1928*4882a593Smuzhiyun 	u32 start;
1929*4882a593Smuzhiyun 	int rc;
1930*4882a593Smuzhiyun 	static u32 reqid = IPSEC_MANUAL_REQID_MAX;
1931*4882a593Smuzhiyun 
1932*4882a593Smuzhiyun 	start = reqid;
1933*4882a593Smuzhiyun 	do {
1934*4882a593Smuzhiyun 		++reqid;
1935*4882a593Smuzhiyun 		if (reqid == 0)
1936*4882a593Smuzhiyun 			reqid = IPSEC_MANUAL_REQID_MAX+1;
1937*4882a593Smuzhiyun 		xfrm_policy_walk_init(&walk, XFRM_POLICY_TYPE_MAIN);
1938*4882a593Smuzhiyun 		rc = xfrm_policy_walk(net, &walk, check_reqid, (void*)&reqid);
1939*4882a593Smuzhiyun 		xfrm_policy_walk_done(&walk, net);
1940*4882a593Smuzhiyun 		if (rc != -EEXIST)
1941*4882a593Smuzhiyun 			return reqid;
1942*4882a593Smuzhiyun 	} while (reqid != start);
1943*4882a593Smuzhiyun 	return 0;
1944*4882a593Smuzhiyun }
1945*4882a593Smuzhiyun 
1946*4882a593Smuzhiyun static int
parse_ipsecrequest(struct xfrm_policy * xp,struct sadb_x_ipsecrequest * rq)1947*4882a593Smuzhiyun parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
1948*4882a593Smuzhiyun {
1949*4882a593Smuzhiyun 	struct net *net = xp_net(xp);
1950*4882a593Smuzhiyun 	struct xfrm_tmpl *t = xp->xfrm_vec + xp->xfrm_nr;
1951*4882a593Smuzhiyun 	int mode;
1952*4882a593Smuzhiyun 
1953*4882a593Smuzhiyun 	if (xp->xfrm_nr >= XFRM_MAX_DEPTH)
1954*4882a593Smuzhiyun 		return -ELOOP;
1955*4882a593Smuzhiyun 
1956*4882a593Smuzhiyun 	if (rq->sadb_x_ipsecrequest_mode == 0)
1957*4882a593Smuzhiyun 		return -EINVAL;
1958*4882a593Smuzhiyun 	if (!xfrm_id_proto_valid(rq->sadb_x_ipsecrequest_proto))
1959*4882a593Smuzhiyun 		return -EINVAL;
1960*4882a593Smuzhiyun 
1961*4882a593Smuzhiyun 	t->id.proto = rq->sadb_x_ipsecrequest_proto;
1962*4882a593Smuzhiyun 	if ((mode = pfkey_mode_to_xfrm(rq->sadb_x_ipsecrequest_mode)) < 0)
1963*4882a593Smuzhiyun 		return -EINVAL;
1964*4882a593Smuzhiyun 	t->mode = mode;
1965*4882a593Smuzhiyun 	if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_USE)
1966*4882a593Smuzhiyun 		t->optional = 1;
1967*4882a593Smuzhiyun 	else if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_UNIQUE) {
1968*4882a593Smuzhiyun 		t->reqid = rq->sadb_x_ipsecrequest_reqid;
1969*4882a593Smuzhiyun 		if (t->reqid > IPSEC_MANUAL_REQID_MAX)
1970*4882a593Smuzhiyun 			t->reqid = 0;
1971*4882a593Smuzhiyun 		if (!t->reqid && !(t->reqid = gen_reqid(net)))
1972*4882a593Smuzhiyun 			return -ENOBUFS;
1973*4882a593Smuzhiyun 	}
1974*4882a593Smuzhiyun 
1975*4882a593Smuzhiyun 	/* addresses present only in tunnel mode */
1976*4882a593Smuzhiyun 	if (t->mode == XFRM_MODE_TUNNEL) {
1977*4882a593Smuzhiyun 		int err;
1978*4882a593Smuzhiyun 
1979*4882a593Smuzhiyun 		err = parse_sockaddr_pair(
1980*4882a593Smuzhiyun 			(struct sockaddr *)(rq + 1),
1981*4882a593Smuzhiyun 			rq->sadb_x_ipsecrequest_len - sizeof(*rq),
1982*4882a593Smuzhiyun 			&t->saddr, &t->id.daddr, &t->encap_family);
1983*4882a593Smuzhiyun 		if (err)
1984*4882a593Smuzhiyun 			return err;
1985*4882a593Smuzhiyun 	} else
1986*4882a593Smuzhiyun 		t->encap_family = xp->family;
1987*4882a593Smuzhiyun 
1988*4882a593Smuzhiyun 	/* No way to set this via kame pfkey */
1989*4882a593Smuzhiyun 	t->allalgs = 1;
1990*4882a593Smuzhiyun 	xp->xfrm_nr++;
1991*4882a593Smuzhiyun 	return 0;
1992*4882a593Smuzhiyun }
1993*4882a593Smuzhiyun 
1994*4882a593Smuzhiyun static int
parse_ipsecrequests(struct xfrm_policy * xp,struct sadb_x_policy * pol)1995*4882a593Smuzhiyun parse_ipsecrequests(struct xfrm_policy *xp, struct sadb_x_policy *pol)
1996*4882a593Smuzhiyun {
1997*4882a593Smuzhiyun 	int err;
1998*4882a593Smuzhiyun 	int len = pol->sadb_x_policy_len*8 - sizeof(struct sadb_x_policy);
1999*4882a593Smuzhiyun 	struct sadb_x_ipsecrequest *rq = (void*)(pol+1);
2000*4882a593Smuzhiyun 
2001*4882a593Smuzhiyun 	if (pol->sadb_x_policy_len * 8 < sizeof(struct sadb_x_policy))
2002*4882a593Smuzhiyun 		return -EINVAL;
2003*4882a593Smuzhiyun 
2004*4882a593Smuzhiyun 	while (len >= sizeof(*rq)) {
2005*4882a593Smuzhiyun 		if (len < rq->sadb_x_ipsecrequest_len ||
2006*4882a593Smuzhiyun 		    rq->sadb_x_ipsecrequest_len < sizeof(*rq))
2007*4882a593Smuzhiyun 			return -EINVAL;
2008*4882a593Smuzhiyun 
2009*4882a593Smuzhiyun 		if ((err = parse_ipsecrequest(xp, rq)) < 0)
2010*4882a593Smuzhiyun 			return err;
2011*4882a593Smuzhiyun 		len -= rq->sadb_x_ipsecrequest_len;
2012*4882a593Smuzhiyun 		rq = (void*)((u8*)rq + rq->sadb_x_ipsecrequest_len);
2013*4882a593Smuzhiyun 	}
2014*4882a593Smuzhiyun 	return 0;
2015*4882a593Smuzhiyun }
2016*4882a593Smuzhiyun 
pfkey_xfrm_policy2sec_ctx_size(const struct xfrm_policy * xp)2017*4882a593Smuzhiyun static inline int pfkey_xfrm_policy2sec_ctx_size(const struct xfrm_policy *xp)
2018*4882a593Smuzhiyun {
2019*4882a593Smuzhiyun 	struct xfrm_sec_ctx *xfrm_ctx = xp->security;
2020*4882a593Smuzhiyun 
2021*4882a593Smuzhiyun 	if (xfrm_ctx) {
2022*4882a593Smuzhiyun 		int len = sizeof(struct sadb_x_sec_ctx);
2023*4882a593Smuzhiyun 		len += xfrm_ctx->ctx_len;
2024*4882a593Smuzhiyun 		return PFKEY_ALIGN8(len);
2025*4882a593Smuzhiyun 	}
2026*4882a593Smuzhiyun 	return 0;
2027*4882a593Smuzhiyun }
2028*4882a593Smuzhiyun 
pfkey_xfrm_policy2msg_size(const struct xfrm_policy * xp)2029*4882a593Smuzhiyun static int pfkey_xfrm_policy2msg_size(const struct xfrm_policy *xp)
2030*4882a593Smuzhiyun {
2031*4882a593Smuzhiyun 	const struct xfrm_tmpl *t;
2032*4882a593Smuzhiyun 	int sockaddr_size = pfkey_sockaddr_size(xp->family);
2033*4882a593Smuzhiyun 	int socklen = 0;
2034*4882a593Smuzhiyun 	int i;
2035*4882a593Smuzhiyun 
2036*4882a593Smuzhiyun 	for (i=0; i<xp->xfrm_nr; i++) {
2037*4882a593Smuzhiyun 		t = xp->xfrm_vec + i;
2038*4882a593Smuzhiyun 		socklen += pfkey_sockaddr_len(t->encap_family);
2039*4882a593Smuzhiyun 	}
2040*4882a593Smuzhiyun 
2041*4882a593Smuzhiyun 	return sizeof(struct sadb_msg) +
2042*4882a593Smuzhiyun 		(sizeof(struct sadb_lifetime) * 3) +
2043*4882a593Smuzhiyun 		(sizeof(struct sadb_address) * 2) +
2044*4882a593Smuzhiyun 		(sockaddr_size * 2) +
2045*4882a593Smuzhiyun 		sizeof(struct sadb_x_policy) +
2046*4882a593Smuzhiyun 		(xp->xfrm_nr * sizeof(struct sadb_x_ipsecrequest)) +
2047*4882a593Smuzhiyun 		(socklen * 2) +
2048*4882a593Smuzhiyun 		pfkey_xfrm_policy2sec_ctx_size(xp);
2049*4882a593Smuzhiyun }
2050*4882a593Smuzhiyun 
pfkey_xfrm_policy2msg_prep(const struct xfrm_policy * xp)2051*4882a593Smuzhiyun static struct sk_buff * pfkey_xfrm_policy2msg_prep(const struct xfrm_policy *xp)
2052*4882a593Smuzhiyun {
2053*4882a593Smuzhiyun 	struct sk_buff *skb;
2054*4882a593Smuzhiyun 	int size;
2055*4882a593Smuzhiyun 
2056*4882a593Smuzhiyun 	size = pfkey_xfrm_policy2msg_size(xp);
2057*4882a593Smuzhiyun 
2058*4882a593Smuzhiyun 	skb =  alloc_skb(size + 16, GFP_ATOMIC);
2059*4882a593Smuzhiyun 	if (skb == NULL)
2060*4882a593Smuzhiyun 		return ERR_PTR(-ENOBUFS);
2061*4882a593Smuzhiyun 
2062*4882a593Smuzhiyun 	return skb;
2063*4882a593Smuzhiyun }
2064*4882a593Smuzhiyun 
pfkey_xfrm_policy2msg(struct sk_buff * skb,const struct xfrm_policy * xp,int dir)2065*4882a593Smuzhiyun static int pfkey_xfrm_policy2msg(struct sk_buff *skb, const struct xfrm_policy *xp, int dir)
2066*4882a593Smuzhiyun {
2067*4882a593Smuzhiyun 	struct sadb_msg *hdr;
2068*4882a593Smuzhiyun 	struct sadb_address *addr;
2069*4882a593Smuzhiyun 	struct sadb_lifetime *lifetime;
2070*4882a593Smuzhiyun 	struct sadb_x_policy *pol;
2071*4882a593Smuzhiyun 	struct sadb_x_sec_ctx *sec_ctx;
2072*4882a593Smuzhiyun 	struct xfrm_sec_ctx *xfrm_ctx;
2073*4882a593Smuzhiyun 	int i;
2074*4882a593Smuzhiyun 	int size;
2075*4882a593Smuzhiyun 	int sockaddr_size = pfkey_sockaddr_size(xp->family);
2076*4882a593Smuzhiyun 	int socklen = pfkey_sockaddr_len(xp->family);
2077*4882a593Smuzhiyun 
2078*4882a593Smuzhiyun 	size = pfkey_xfrm_policy2msg_size(xp);
2079*4882a593Smuzhiyun 
2080*4882a593Smuzhiyun 	/* call should fill header later */
2081*4882a593Smuzhiyun 	hdr = skb_put(skb, sizeof(struct sadb_msg));
2082*4882a593Smuzhiyun 	memset(hdr, 0, size);	/* XXX do we need this ? */
2083*4882a593Smuzhiyun 
2084*4882a593Smuzhiyun 	/* src address */
2085*4882a593Smuzhiyun 	addr = skb_put(skb, sizeof(struct sadb_address) + sockaddr_size);
2086*4882a593Smuzhiyun 	addr->sadb_address_len =
2087*4882a593Smuzhiyun 		(sizeof(struct sadb_address)+sockaddr_size)/
2088*4882a593Smuzhiyun 			sizeof(uint64_t);
2089*4882a593Smuzhiyun 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
2090*4882a593Smuzhiyun 	addr->sadb_address_proto = pfkey_proto_from_xfrm(xp->selector.proto);
2091*4882a593Smuzhiyun 	addr->sadb_address_prefixlen = xp->selector.prefixlen_s;
2092*4882a593Smuzhiyun 	addr->sadb_address_reserved = 0;
2093*4882a593Smuzhiyun 	if (!pfkey_sockaddr_fill(&xp->selector.saddr,
2094*4882a593Smuzhiyun 				 xp->selector.sport,
2095*4882a593Smuzhiyun 				 (struct sockaddr *) (addr + 1),
2096*4882a593Smuzhiyun 				 xp->family))
2097*4882a593Smuzhiyun 		BUG();
2098*4882a593Smuzhiyun 
2099*4882a593Smuzhiyun 	/* dst address */
2100*4882a593Smuzhiyun 	addr = skb_put(skb, sizeof(struct sadb_address) + sockaddr_size);
2101*4882a593Smuzhiyun 	addr->sadb_address_len =
2102*4882a593Smuzhiyun 		(sizeof(struct sadb_address)+sockaddr_size)/
2103*4882a593Smuzhiyun 			sizeof(uint64_t);
2104*4882a593Smuzhiyun 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
2105*4882a593Smuzhiyun 	addr->sadb_address_proto = pfkey_proto_from_xfrm(xp->selector.proto);
2106*4882a593Smuzhiyun 	addr->sadb_address_prefixlen = xp->selector.prefixlen_d;
2107*4882a593Smuzhiyun 	addr->sadb_address_reserved = 0;
2108*4882a593Smuzhiyun 
2109*4882a593Smuzhiyun 	pfkey_sockaddr_fill(&xp->selector.daddr, xp->selector.dport,
2110*4882a593Smuzhiyun 			    (struct sockaddr *) (addr + 1),
2111*4882a593Smuzhiyun 			    xp->family);
2112*4882a593Smuzhiyun 
2113*4882a593Smuzhiyun 	/* hard time */
2114*4882a593Smuzhiyun 	lifetime = skb_put(skb, sizeof(struct sadb_lifetime));
2115*4882a593Smuzhiyun 	lifetime->sadb_lifetime_len =
2116*4882a593Smuzhiyun 		sizeof(struct sadb_lifetime)/sizeof(uint64_t);
2117*4882a593Smuzhiyun 	lifetime->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
2118*4882a593Smuzhiyun 	lifetime->sadb_lifetime_allocations =  _X2KEY(xp->lft.hard_packet_limit);
2119*4882a593Smuzhiyun 	lifetime->sadb_lifetime_bytes = _X2KEY(xp->lft.hard_byte_limit);
2120*4882a593Smuzhiyun 	lifetime->sadb_lifetime_addtime = xp->lft.hard_add_expires_seconds;
2121*4882a593Smuzhiyun 	lifetime->sadb_lifetime_usetime = xp->lft.hard_use_expires_seconds;
2122*4882a593Smuzhiyun 	/* soft time */
2123*4882a593Smuzhiyun 	lifetime = skb_put(skb, sizeof(struct sadb_lifetime));
2124*4882a593Smuzhiyun 	lifetime->sadb_lifetime_len =
2125*4882a593Smuzhiyun 		sizeof(struct sadb_lifetime)/sizeof(uint64_t);
2126*4882a593Smuzhiyun 	lifetime->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
2127*4882a593Smuzhiyun 	lifetime->sadb_lifetime_allocations =  _X2KEY(xp->lft.soft_packet_limit);
2128*4882a593Smuzhiyun 	lifetime->sadb_lifetime_bytes = _X2KEY(xp->lft.soft_byte_limit);
2129*4882a593Smuzhiyun 	lifetime->sadb_lifetime_addtime = xp->lft.soft_add_expires_seconds;
2130*4882a593Smuzhiyun 	lifetime->sadb_lifetime_usetime = xp->lft.soft_use_expires_seconds;
2131*4882a593Smuzhiyun 	/* current time */
2132*4882a593Smuzhiyun 	lifetime = skb_put(skb, sizeof(struct sadb_lifetime));
2133*4882a593Smuzhiyun 	lifetime->sadb_lifetime_len =
2134*4882a593Smuzhiyun 		sizeof(struct sadb_lifetime)/sizeof(uint64_t);
2135*4882a593Smuzhiyun 	lifetime->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT;
2136*4882a593Smuzhiyun 	lifetime->sadb_lifetime_allocations = xp->curlft.packets;
2137*4882a593Smuzhiyun 	lifetime->sadb_lifetime_bytes = xp->curlft.bytes;
2138*4882a593Smuzhiyun 	lifetime->sadb_lifetime_addtime = xp->curlft.add_time;
2139*4882a593Smuzhiyun 	lifetime->sadb_lifetime_usetime = xp->curlft.use_time;
2140*4882a593Smuzhiyun 
2141*4882a593Smuzhiyun 	pol = skb_put(skb, sizeof(struct sadb_x_policy));
2142*4882a593Smuzhiyun 	pol->sadb_x_policy_len = sizeof(struct sadb_x_policy)/sizeof(uint64_t);
2143*4882a593Smuzhiyun 	pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
2144*4882a593Smuzhiyun 	pol->sadb_x_policy_type = IPSEC_POLICY_DISCARD;
2145*4882a593Smuzhiyun 	if (xp->action == XFRM_POLICY_ALLOW) {
2146*4882a593Smuzhiyun 		if (xp->xfrm_nr)
2147*4882a593Smuzhiyun 			pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
2148*4882a593Smuzhiyun 		else
2149*4882a593Smuzhiyun 			pol->sadb_x_policy_type = IPSEC_POLICY_NONE;
2150*4882a593Smuzhiyun 	}
2151*4882a593Smuzhiyun 	pol->sadb_x_policy_dir = dir+1;
2152*4882a593Smuzhiyun 	pol->sadb_x_policy_reserved = 0;
2153*4882a593Smuzhiyun 	pol->sadb_x_policy_id = xp->index;
2154*4882a593Smuzhiyun 	pol->sadb_x_policy_priority = xp->priority;
2155*4882a593Smuzhiyun 
2156*4882a593Smuzhiyun 	for (i=0; i<xp->xfrm_nr; i++) {
2157*4882a593Smuzhiyun 		const struct xfrm_tmpl *t = xp->xfrm_vec + i;
2158*4882a593Smuzhiyun 		struct sadb_x_ipsecrequest *rq;
2159*4882a593Smuzhiyun 		int req_size;
2160*4882a593Smuzhiyun 		int mode;
2161*4882a593Smuzhiyun 
2162*4882a593Smuzhiyun 		req_size = sizeof(struct sadb_x_ipsecrequest);
2163*4882a593Smuzhiyun 		if (t->mode == XFRM_MODE_TUNNEL) {
2164*4882a593Smuzhiyun 			socklen = pfkey_sockaddr_len(t->encap_family);
2165*4882a593Smuzhiyun 			req_size += socklen * 2;
2166*4882a593Smuzhiyun 		} else {
2167*4882a593Smuzhiyun 			size -= 2*socklen;
2168*4882a593Smuzhiyun 		}
2169*4882a593Smuzhiyun 		rq = skb_put(skb, req_size);
2170*4882a593Smuzhiyun 		pol->sadb_x_policy_len += req_size/8;
2171*4882a593Smuzhiyun 		memset(rq, 0, sizeof(*rq));
2172*4882a593Smuzhiyun 		rq->sadb_x_ipsecrequest_len = req_size;
2173*4882a593Smuzhiyun 		rq->sadb_x_ipsecrequest_proto = t->id.proto;
2174*4882a593Smuzhiyun 		if ((mode = pfkey_mode_from_xfrm(t->mode)) < 0)
2175*4882a593Smuzhiyun 			return -EINVAL;
2176*4882a593Smuzhiyun 		rq->sadb_x_ipsecrequest_mode = mode;
2177*4882a593Smuzhiyun 		rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE;
2178*4882a593Smuzhiyun 		if (t->reqid)
2179*4882a593Smuzhiyun 			rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE;
2180*4882a593Smuzhiyun 		if (t->optional)
2181*4882a593Smuzhiyun 			rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_USE;
2182*4882a593Smuzhiyun 		rq->sadb_x_ipsecrequest_reqid = t->reqid;
2183*4882a593Smuzhiyun 
2184*4882a593Smuzhiyun 		if (t->mode == XFRM_MODE_TUNNEL) {
2185*4882a593Smuzhiyun 			u8 *sa = (void *)(rq + 1);
2186*4882a593Smuzhiyun 			pfkey_sockaddr_fill(&t->saddr, 0,
2187*4882a593Smuzhiyun 					    (struct sockaddr *)sa,
2188*4882a593Smuzhiyun 					    t->encap_family);
2189*4882a593Smuzhiyun 			pfkey_sockaddr_fill(&t->id.daddr, 0,
2190*4882a593Smuzhiyun 					    (struct sockaddr *) (sa + socklen),
2191*4882a593Smuzhiyun 					    t->encap_family);
2192*4882a593Smuzhiyun 		}
2193*4882a593Smuzhiyun 	}
2194*4882a593Smuzhiyun 
2195*4882a593Smuzhiyun 	/* security context */
2196*4882a593Smuzhiyun 	if ((xfrm_ctx = xp->security)) {
2197*4882a593Smuzhiyun 		int ctx_size = pfkey_xfrm_policy2sec_ctx_size(xp);
2198*4882a593Smuzhiyun 
2199*4882a593Smuzhiyun 		sec_ctx = skb_put(skb, ctx_size);
2200*4882a593Smuzhiyun 		sec_ctx->sadb_x_sec_len = ctx_size / sizeof(uint64_t);
2201*4882a593Smuzhiyun 		sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
2202*4882a593Smuzhiyun 		sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi;
2203*4882a593Smuzhiyun 		sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg;
2204*4882a593Smuzhiyun 		sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len;
2205*4882a593Smuzhiyun 		memcpy(sec_ctx + 1, xfrm_ctx->ctx_str,
2206*4882a593Smuzhiyun 		       xfrm_ctx->ctx_len);
2207*4882a593Smuzhiyun 	}
2208*4882a593Smuzhiyun 
2209*4882a593Smuzhiyun 	hdr->sadb_msg_len = size / sizeof(uint64_t);
2210*4882a593Smuzhiyun 	hdr->sadb_msg_reserved = refcount_read(&xp->refcnt);
2211*4882a593Smuzhiyun 
2212*4882a593Smuzhiyun 	return 0;
2213*4882a593Smuzhiyun }
2214*4882a593Smuzhiyun 
key_notify_policy(struct xfrm_policy * xp,int dir,const struct km_event * c)2215*4882a593Smuzhiyun static int key_notify_policy(struct xfrm_policy *xp, int dir, const struct km_event *c)
2216*4882a593Smuzhiyun {
2217*4882a593Smuzhiyun 	struct sk_buff *out_skb;
2218*4882a593Smuzhiyun 	struct sadb_msg *out_hdr;
2219*4882a593Smuzhiyun 	int err;
2220*4882a593Smuzhiyun 
2221*4882a593Smuzhiyun 	out_skb = pfkey_xfrm_policy2msg_prep(xp);
2222*4882a593Smuzhiyun 	if (IS_ERR(out_skb))
2223*4882a593Smuzhiyun 		return PTR_ERR(out_skb);
2224*4882a593Smuzhiyun 
2225*4882a593Smuzhiyun 	err = pfkey_xfrm_policy2msg(out_skb, xp, dir);
2226*4882a593Smuzhiyun 	if (err < 0) {
2227*4882a593Smuzhiyun 		kfree_skb(out_skb);
2228*4882a593Smuzhiyun 		return err;
2229*4882a593Smuzhiyun 	}
2230*4882a593Smuzhiyun 
2231*4882a593Smuzhiyun 	out_hdr = (struct sadb_msg *) out_skb->data;
2232*4882a593Smuzhiyun 	out_hdr->sadb_msg_version = PF_KEY_V2;
2233*4882a593Smuzhiyun 
2234*4882a593Smuzhiyun 	if (c->data.byid && c->event == XFRM_MSG_DELPOLICY)
2235*4882a593Smuzhiyun 		out_hdr->sadb_msg_type = SADB_X_SPDDELETE2;
2236*4882a593Smuzhiyun 	else
2237*4882a593Smuzhiyun 		out_hdr->sadb_msg_type = event2poltype(c->event);
2238*4882a593Smuzhiyun 	out_hdr->sadb_msg_errno = 0;
2239*4882a593Smuzhiyun 	out_hdr->sadb_msg_seq = c->seq;
2240*4882a593Smuzhiyun 	out_hdr->sadb_msg_pid = c->portid;
2241*4882a593Smuzhiyun 	pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, NULL, xp_net(xp));
2242*4882a593Smuzhiyun 	return 0;
2243*4882a593Smuzhiyun 
2244*4882a593Smuzhiyun }
2245*4882a593Smuzhiyun 
pfkey_spdadd(struct sock * sk,struct sk_buff * skb,const struct sadb_msg * hdr,void * const * ext_hdrs)2246*4882a593Smuzhiyun static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
2247*4882a593Smuzhiyun {
2248*4882a593Smuzhiyun 	struct net *net = sock_net(sk);
2249*4882a593Smuzhiyun 	int err = 0;
2250*4882a593Smuzhiyun 	struct sadb_lifetime *lifetime;
2251*4882a593Smuzhiyun 	struct sadb_address *sa;
2252*4882a593Smuzhiyun 	struct sadb_x_policy *pol;
2253*4882a593Smuzhiyun 	struct xfrm_policy *xp;
2254*4882a593Smuzhiyun 	struct km_event c;
2255*4882a593Smuzhiyun 	struct sadb_x_sec_ctx *sec_ctx;
2256*4882a593Smuzhiyun 
2257*4882a593Smuzhiyun 	if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
2258*4882a593Smuzhiyun 				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
2259*4882a593Smuzhiyun 	    !ext_hdrs[SADB_X_EXT_POLICY-1])
2260*4882a593Smuzhiyun 		return -EINVAL;
2261*4882a593Smuzhiyun 
2262*4882a593Smuzhiyun 	pol = ext_hdrs[SADB_X_EXT_POLICY-1];
2263*4882a593Smuzhiyun 	if (pol->sadb_x_policy_type > IPSEC_POLICY_IPSEC)
2264*4882a593Smuzhiyun 		return -EINVAL;
2265*4882a593Smuzhiyun 	if (!pol->sadb_x_policy_dir || pol->sadb_x_policy_dir >= IPSEC_DIR_MAX)
2266*4882a593Smuzhiyun 		return -EINVAL;
2267*4882a593Smuzhiyun 
2268*4882a593Smuzhiyun 	xp = xfrm_policy_alloc(net, GFP_KERNEL);
2269*4882a593Smuzhiyun 	if (xp == NULL)
2270*4882a593Smuzhiyun 		return -ENOBUFS;
2271*4882a593Smuzhiyun 
2272*4882a593Smuzhiyun 	xp->action = (pol->sadb_x_policy_type == IPSEC_POLICY_DISCARD ?
2273*4882a593Smuzhiyun 		      XFRM_POLICY_BLOCK : XFRM_POLICY_ALLOW);
2274*4882a593Smuzhiyun 	xp->priority = pol->sadb_x_policy_priority;
2275*4882a593Smuzhiyun 
2276*4882a593Smuzhiyun 	sa = ext_hdrs[SADB_EXT_ADDRESS_SRC-1];
2277*4882a593Smuzhiyun 	xp->family = pfkey_sadb_addr2xfrm_addr(sa, &xp->selector.saddr);
2278*4882a593Smuzhiyun 	xp->selector.family = xp->family;
2279*4882a593Smuzhiyun 	xp->selector.prefixlen_s = sa->sadb_address_prefixlen;
2280*4882a593Smuzhiyun 	xp->selector.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
2281*4882a593Smuzhiyun 	xp->selector.sport = ((struct sockaddr_in *)(sa+1))->sin_port;
2282*4882a593Smuzhiyun 	if (xp->selector.sport)
2283*4882a593Smuzhiyun 		xp->selector.sport_mask = htons(0xffff);
2284*4882a593Smuzhiyun 
2285*4882a593Smuzhiyun 	sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1];
2286*4882a593Smuzhiyun 	pfkey_sadb_addr2xfrm_addr(sa, &xp->selector.daddr);
2287*4882a593Smuzhiyun 	xp->selector.prefixlen_d = sa->sadb_address_prefixlen;
2288*4882a593Smuzhiyun 
2289*4882a593Smuzhiyun 	/* Amusing, we set this twice.  KAME apps appear to set same value
2290*4882a593Smuzhiyun 	 * in both addresses.
2291*4882a593Smuzhiyun 	 */
2292*4882a593Smuzhiyun 	xp->selector.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
2293*4882a593Smuzhiyun 
2294*4882a593Smuzhiyun 	xp->selector.dport = ((struct sockaddr_in *)(sa+1))->sin_port;
2295*4882a593Smuzhiyun 	if (xp->selector.dport)
2296*4882a593Smuzhiyun 		xp->selector.dport_mask = htons(0xffff);
2297*4882a593Smuzhiyun 
2298*4882a593Smuzhiyun 	sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1];
2299*4882a593Smuzhiyun 	if (sec_ctx != NULL) {
2300*4882a593Smuzhiyun 		struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx, GFP_KERNEL);
2301*4882a593Smuzhiyun 
2302*4882a593Smuzhiyun 		if (!uctx) {
2303*4882a593Smuzhiyun 			err = -ENOBUFS;
2304*4882a593Smuzhiyun 			goto out;
2305*4882a593Smuzhiyun 		}
2306*4882a593Smuzhiyun 
2307*4882a593Smuzhiyun 		err = security_xfrm_policy_alloc(&xp->security, uctx, GFP_KERNEL);
2308*4882a593Smuzhiyun 		kfree(uctx);
2309*4882a593Smuzhiyun 
2310*4882a593Smuzhiyun 		if (err)
2311*4882a593Smuzhiyun 			goto out;
2312*4882a593Smuzhiyun 	}
2313*4882a593Smuzhiyun 
2314*4882a593Smuzhiyun 	xp->lft.soft_byte_limit = XFRM_INF;
2315*4882a593Smuzhiyun 	xp->lft.hard_byte_limit = XFRM_INF;
2316*4882a593Smuzhiyun 	xp->lft.soft_packet_limit = XFRM_INF;
2317*4882a593Smuzhiyun 	xp->lft.hard_packet_limit = XFRM_INF;
2318*4882a593Smuzhiyun 	if ((lifetime = ext_hdrs[SADB_EXT_LIFETIME_HARD-1]) != NULL) {
2319*4882a593Smuzhiyun 		xp->lft.hard_packet_limit = _KEY2X(lifetime->sadb_lifetime_allocations);
2320*4882a593Smuzhiyun 		xp->lft.hard_byte_limit = _KEY2X(lifetime->sadb_lifetime_bytes);
2321*4882a593Smuzhiyun 		xp->lft.hard_add_expires_seconds = lifetime->sadb_lifetime_addtime;
2322*4882a593Smuzhiyun 		xp->lft.hard_use_expires_seconds = lifetime->sadb_lifetime_usetime;
2323*4882a593Smuzhiyun 	}
2324*4882a593Smuzhiyun 	if ((lifetime = ext_hdrs[SADB_EXT_LIFETIME_SOFT-1]) != NULL) {
2325*4882a593Smuzhiyun 		xp->lft.soft_packet_limit = _KEY2X(lifetime->sadb_lifetime_allocations);
2326*4882a593Smuzhiyun 		xp->lft.soft_byte_limit = _KEY2X(lifetime->sadb_lifetime_bytes);
2327*4882a593Smuzhiyun 		xp->lft.soft_add_expires_seconds = lifetime->sadb_lifetime_addtime;
2328*4882a593Smuzhiyun 		xp->lft.soft_use_expires_seconds = lifetime->sadb_lifetime_usetime;
2329*4882a593Smuzhiyun 	}
2330*4882a593Smuzhiyun 	xp->xfrm_nr = 0;
2331*4882a593Smuzhiyun 	if (pol->sadb_x_policy_type == IPSEC_POLICY_IPSEC &&
2332*4882a593Smuzhiyun 	    (err = parse_ipsecrequests(xp, pol)) < 0)
2333*4882a593Smuzhiyun 		goto out;
2334*4882a593Smuzhiyun 
2335*4882a593Smuzhiyun 	err = xfrm_policy_insert(pol->sadb_x_policy_dir-1, xp,
2336*4882a593Smuzhiyun 				 hdr->sadb_msg_type != SADB_X_SPDUPDATE);
2337*4882a593Smuzhiyun 
2338*4882a593Smuzhiyun 	xfrm_audit_policy_add(xp, err ? 0 : 1, true);
2339*4882a593Smuzhiyun 
2340*4882a593Smuzhiyun 	if (err)
2341*4882a593Smuzhiyun 		goto out;
2342*4882a593Smuzhiyun 
2343*4882a593Smuzhiyun 	if (hdr->sadb_msg_type == SADB_X_SPDUPDATE)
2344*4882a593Smuzhiyun 		c.event = XFRM_MSG_UPDPOLICY;
2345*4882a593Smuzhiyun 	else
2346*4882a593Smuzhiyun 		c.event = XFRM_MSG_NEWPOLICY;
2347*4882a593Smuzhiyun 
2348*4882a593Smuzhiyun 	c.seq = hdr->sadb_msg_seq;
2349*4882a593Smuzhiyun 	c.portid = hdr->sadb_msg_pid;
2350*4882a593Smuzhiyun 
2351*4882a593Smuzhiyun 	km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c);
2352*4882a593Smuzhiyun 	xfrm_pol_put(xp);
2353*4882a593Smuzhiyun 	return 0;
2354*4882a593Smuzhiyun 
2355*4882a593Smuzhiyun out:
2356*4882a593Smuzhiyun 	xp->walk.dead = 1;
2357*4882a593Smuzhiyun 	xfrm_policy_destroy(xp);
2358*4882a593Smuzhiyun 	return err;
2359*4882a593Smuzhiyun }
2360*4882a593Smuzhiyun 
pfkey_spddelete(struct sock * sk,struct sk_buff * skb,const struct sadb_msg * hdr,void * const * ext_hdrs)2361*4882a593Smuzhiyun static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
2362*4882a593Smuzhiyun {
2363*4882a593Smuzhiyun 	struct net *net = sock_net(sk);
2364*4882a593Smuzhiyun 	int err;
2365*4882a593Smuzhiyun 	struct sadb_address *sa;
2366*4882a593Smuzhiyun 	struct sadb_x_policy *pol;
2367*4882a593Smuzhiyun 	struct xfrm_policy *xp;
2368*4882a593Smuzhiyun 	struct xfrm_selector sel;
2369*4882a593Smuzhiyun 	struct km_event c;
2370*4882a593Smuzhiyun 	struct sadb_x_sec_ctx *sec_ctx;
2371*4882a593Smuzhiyun 	struct xfrm_sec_ctx *pol_ctx = NULL;
2372*4882a593Smuzhiyun 
2373*4882a593Smuzhiyun 	if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
2374*4882a593Smuzhiyun 				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
2375*4882a593Smuzhiyun 	    !ext_hdrs[SADB_X_EXT_POLICY-1])
2376*4882a593Smuzhiyun 		return -EINVAL;
2377*4882a593Smuzhiyun 
2378*4882a593Smuzhiyun 	pol = ext_hdrs[SADB_X_EXT_POLICY-1];
2379*4882a593Smuzhiyun 	if (!pol->sadb_x_policy_dir || pol->sadb_x_policy_dir >= IPSEC_DIR_MAX)
2380*4882a593Smuzhiyun 		return -EINVAL;
2381*4882a593Smuzhiyun 
2382*4882a593Smuzhiyun 	memset(&sel, 0, sizeof(sel));
2383*4882a593Smuzhiyun 
2384*4882a593Smuzhiyun 	sa = ext_hdrs[SADB_EXT_ADDRESS_SRC-1];
2385*4882a593Smuzhiyun 	sel.family = pfkey_sadb_addr2xfrm_addr(sa, &sel.saddr);
2386*4882a593Smuzhiyun 	sel.prefixlen_s = sa->sadb_address_prefixlen;
2387*4882a593Smuzhiyun 	sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
2388*4882a593Smuzhiyun 	sel.sport = ((struct sockaddr_in *)(sa+1))->sin_port;
2389*4882a593Smuzhiyun 	if (sel.sport)
2390*4882a593Smuzhiyun 		sel.sport_mask = htons(0xffff);
2391*4882a593Smuzhiyun 
2392*4882a593Smuzhiyun 	sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1];
2393*4882a593Smuzhiyun 	pfkey_sadb_addr2xfrm_addr(sa, &sel.daddr);
2394*4882a593Smuzhiyun 	sel.prefixlen_d = sa->sadb_address_prefixlen;
2395*4882a593Smuzhiyun 	sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
2396*4882a593Smuzhiyun 	sel.dport = ((struct sockaddr_in *)(sa+1))->sin_port;
2397*4882a593Smuzhiyun 	if (sel.dport)
2398*4882a593Smuzhiyun 		sel.dport_mask = htons(0xffff);
2399*4882a593Smuzhiyun 
2400*4882a593Smuzhiyun 	sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1];
2401*4882a593Smuzhiyun 	if (sec_ctx != NULL) {
2402*4882a593Smuzhiyun 		struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx, GFP_KERNEL);
2403*4882a593Smuzhiyun 
2404*4882a593Smuzhiyun 		if (!uctx)
2405*4882a593Smuzhiyun 			return -ENOMEM;
2406*4882a593Smuzhiyun 
2407*4882a593Smuzhiyun 		err = security_xfrm_policy_alloc(&pol_ctx, uctx, GFP_KERNEL);
2408*4882a593Smuzhiyun 		kfree(uctx);
2409*4882a593Smuzhiyun 		if (err)
2410*4882a593Smuzhiyun 			return err;
2411*4882a593Smuzhiyun 	}
2412*4882a593Smuzhiyun 
2413*4882a593Smuzhiyun 	xp = xfrm_policy_bysel_ctx(net, &dummy_mark, 0, XFRM_POLICY_TYPE_MAIN,
2414*4882a593Smuzhiyun 				   pol->sadb_x_policy_dir - 1, &sel, pol_ctx,
2415*4882a593Smuzhiyun 				   1, &err);
2416*4882a593Smuzhiyun 	security_xfrm_policy_free(pol_ctx);
2417*4882a593Smuzhiyun 	if (xp == NULL)
2418*4882a593Smuzhiyun 		return -ENOENT;
2419*4882a593Smuzhiyun 
2420*4882a593Smuzhiyun 	xfrm_audit_policy_delete(xp, err ? 0 : 1, true);
2421*4882a593Smuzhiyun 
2422*4882a593Smuzhiyun 	if (err)
2423*4882a593Smuzhiyun 		goto out;
2424*4882a593Smuzhiyun 
2425*4882a593Smuzhiyun 	c.seq = hdr->sadb_msg_seq;
2426*4882a593Smuzhiyun 	c.portid = hdr->sadb_msg_pid;
2427*4882a593Smuzhiyun 	c.data.byid = 0;
2428*4882a593Smuzhiyun 	c.event = XFRM_MSG_DELPOLICY;
2429*4882a593Smuzhiyun 	km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c);
2430*4882a593Smuzhiyun 
2431*4882a593Smuzhiyun out:
2432*4882a593Smuzhiyun 	xfrm_pol_put(xp);
2433*4882a593Smuzhiyun 	return err;
2434*4882a593Smuzhiyun }
2435*4882a593Smuzhiyun 
key_pol_get_resp(struct sock * sk,struct xfrm_policy * xp,const struct sadb_msg * hdr,int dir)2436*4882a593Smuzhiyun static int key_pol_get_resp(struct sock *sk, struct xfrm_policy *xp, const struct sadb_msg *hdr, int dir)
2437*4882a593Smuzhiyun {
2438*4882a593Smuzhiyun 	int err;
2439*4882a593Smuzhiyun 	struct sk_buff *out_skb;
2440*4882a593Smuzhiyun 	struct sadb_msg *out_hdr;
2441*4882a593Smuzhiyun 	err = 0;
2442*4882a593Smuzhiyun 
2443*4882a593Smuzhiyun 	out_skb = pfkey_xfrm_policy2msg_prep(xp);
2444*4882a593Smuzhiyun 	if (IS_ERR(out_skb)) {
2445*4882a593Smuzhiyun 		err =  PTR_ERR(out_skb);
2446*4882a593Smuzhiyun 		goto out;
2447*4882a593Smuzhiyun 	}
2448*4882a593Smuzhiyun 	err = pfkey_xfrm_policy2msg(out_skb, xp, dir);
2449*4882a593Smuzhiyun 	if (err < 0) {
2450*4882a593Smuzhiyun 		kfree_skb(out_skb);
2451*4882a593Smuzhiyun 		goto out;
2452*4882a593Smuzhiyun 	}
2453*4882a593Smuzhiyun 
2454*4882a593Smuzhiyun 	out_hdr = (struct sadb_msg *) out_skb->data;
2455*4882a593Smuzhiyun 	out_hdr->sadb_msg_version = hdr->sadb_msg_version;
2456*4882a593Smuzhiyun 	out_hdr->sadb_msg_type = hdr->sadb_msg_type;
2457*4882a593Smuzhiyun 	out_hdr->sadb_msg_satype = 0;
2458*4882a593Smuzhiyun 	out_hdr->sadb_msg_errno = 0;
2459*4882a593Smuzhiyun 	out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
2460*4882a593Smuzhiyun 	out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
2461*4882a593Smuzhiyun 	pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk, xp_net(xp));
2462*4882a593Smuzhiyun 	err = 0;
2463*4882a593Smuzhiyun 
2464*4882a593Smuzhiyun out:
2465*4882a593Smuzhiyun 	return err;
2466*4882a593Smuzhiyun }
2467*4882a593Smuzhiyun 
pfkey_sockaddr_pair_size(sa_family_t family)2468*4882a593Smuzhiyun static int pfkey_sockaddr_pair_size(sa_family_t family)
2469*4882a593Smuzhiyun {
2470*4882a593Smuzhiyun 	return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2);
2471*4882a593Smuzhiyun }
2472*4882a593Smuzhiyun 
parse_sockaddr_pair(struct sockaddr * sa,int ext_len,xfrm_address_t * saddr,xfrm_address_t * daddr,u16 * family)2473*4882a593Smuzhiyun static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len,
2474*4882a593Smuzhiyun 			       xfrm_address_t *saddr, xfrm_address_t *daddr,
2475*4882a593Smuzhiyun 			       u16 *family)
2476*4882a593Smuzhiyun {
2477*4882a593Smuzhiyun 	int af, socklen;
2478*4882a593Smuzhiyun 
2479*4882a593Smuzhiyun 	if (ext_len < 2 || ext_len < pfkey_sockaddr_pair_size(sa->sa_family))
2480*4882a593Smuzhiyun 		return -EINVAL;
2481*4882a593Smuzhiyun 
2482*4882a593Smuzhiyun 	af = pfkey_sockaddr_extract(sa, saddr);
2483*4882a593Smuzhiyun 	if (!af)
2484*4882a593Smuzhiyun 		return -EINVAL;
2485*4882a593Smuzhiyun 
2486*4882a593Smuzhiyun 	socklen = pfkey_sockaddr_len(af);
2487*4882a593Smuzhiyun 	if (pfkey_sockaddr_extract((struct sockaddr *) (((u8 *)sa) + socklen),
2488*4882a593Smuzhiyun 				   daddr) != af)
2489*4882a593Smuzhiyun 		return -EINVAL;
2490*4882a593Smuzhiyun 
2491*4882a593Smuzhiyun 	*family = af;
2492*4882a593Smuzhiyun 	return 0;
2493*4882a593Smuzhiyun }
2494*4882a593Smuzhiyun 
2495*4882a593Smuzhiyun #ifdef CONFIG_NET_KEY_MIGRATE
ipsecrequests_to_migrate(struct sadb_x_ipsecrequest * rq1,int len,struct xfrm_migrate * m)2496*4882a593Smuzhiyun static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len,
2497*4882a593Smuzhiyun 				    struct xfrm_migrate *m)
2498*4882a593Smuzhiyun {
2499*4882a593Smuzhiyun 	int err;
2500*4882a593Smuzhiyun 	struct sadb_x_ipsecrequest *rq2;
2501*4882a593Smuzhiyun 	int mode;
2502*4882a593Smuzhiyun 
2503*4882a593Smuzhiyun 	if (len < sizeof(*rq1) ||
2504*4882a593Smuzhiyun 	    len < rq1->sadb_x_ipsecrequest_len ||
2505*4882a593Smuzhiyun 	    rq1->sadb_x_ipsecrequest_len < sizeof(*rq1))
2506*4882a593Smuzhiyun 		return -EINVAL;
2507*4882a593Smuzhiyun 
2508*4882a593Smuzhiyun 	/* old endoints */
2509*4882a593Smuzhiyun 	err = parse_sockaddr_pair((struct sockaddr *)(rq1 + 1),
2510*4882a593Smuzhiyun 				  rq1->sadb_x_ipsecrequest_len - sizeof(*rq1),
2511*4882a593Smuzhiyun 				  &m->old_saddr, &m->old_daddr,
2512*4882a593Smuzhiyun 				  &m->old_family);
2513*4882a593Smuzhiyun 	if (err)
2514*4882a593Smuzhiyun 		return err;
2515*4882a593Smuzhiyun 
2516*4882a593Smuzhiyun 	rq2 = (struct sadb_x_ipsecrequest *)((u8 *)rq1 + rq1->sadb_x_ipsecrequest_len);
2517*4882a593Smuzhiyun 	len -= rq1->sadb_x_ipsecrequest_len;
2518*4882a593Smuzhiyun 
2519*4882a593Smuzhiyun 	if (len <= sizeof(*rq2) ||
2520*4882a593Smuzhiyun 	    len < rq2->sadb_x_ipsecrequest_len ||
2521*4882a593Smuzhiyun 	    rq2->sadb_x_ipsecrequest_len < sizeof(*rq2))
2522*4882a593Smuzhiyun 		return -EINVAL;
2523*4882a593Smuzhiyun 
2524*4882a593Smuzhiyun 	/* new endpoints */
2525*4882a593Smuzhiyun 	err = parse_sockaddr_pair((struct sockaddr *)(rq2 + 1),
2526*4882a593Smuzhiyun 				  rq2->sadb_x_ipsecrequest_len - sizeof(*rq2),
2527*4882a593Smuzhiyun 				  &m->new_saddr, &m->new_daddr,
2528*4882a593Smuzhiyun 				  &m->new_family);
2529*4882a593Smuzhiyun 	if (err)
2530*4882a593Smuzhiyun 		return err;
2531*4882a593Smuzhiyun 
2532*4882a593Smuzhiyun 	if (rq1->sadb_x_ipsecrequest_proto != rq2->sadb_x_ipsecrequest_proto ||
2533*4882a593Smuzhiyun 	    rq1->sadb_x_ipsecrequest_mode != rq2->sadb_x_ipsecrequest_mode ||
2534*4882a593Smuzhiyun 	    rq1->sadb_x_ipsecrequest_reqid != rq2->sadb_x_ipsecrequest_reqid)
2535*4882a593Smuzhiyun 		return -EINVAL;
2536*4882a593Smuzhiyun 
2537*4882a593Smuzhiyun 	m->proto = rq1->sadb_x_ipsecrequest_proto;
2538*4882a593Smuzhiyun 	if ((mode = pfkey_mode_to_xfrm(rq1->sadb_x_ipsecrequest_mode)) < 0)
2539*4882a593Smuzhiyun 		return -EINVAL;
2540*4882a593Smuzhiyun 	m->mode = mode;
2541*4882a593Smuzhiyun 	m->reqid = rq1->sadb_x_ipsecrequest_reqid;
2542*4882a593Smuzhiyun 
2543*4882a593Smuzhiyun 	return ((int)(rq1->sadb_x_ipsecrequest_len +
2544*4882a593Smuzhiyun 		      rq2->sadb_x_ipsecrequest_len));
2545*4882a593Smuzhiyun }
2546*4882a593Smuzhiyun 
pfkey_migrate(struct sock * sk,struct sk_buff * skb,const struct sadb_msg * hdr,void * const * ext_hdrs)2547*4882a593Smuzhiyun static int pfkey_migrate(struct sock *sk, struct sk_buff *skb,
2548*4882a593Smuzhiyun 			 const struct sadb_msg *hdr, void * const *ext_hdrs)
2549*4882a593Smuzhiyun {
2550*4882a593Smuzhiyun 	int i, len, ret, err = -EINVAL;
2551*4882a593Smuzhiyun 	u8 dir;
2552*4882a593Smuzhiyun 	struct sadb_address *sa;
2553*4882a593Smuzhiyun 	struct sadb_x_kmaddress *kma;
2554*4882a593Smuzhiyun 	struct sadb_x_policy *pol;
2555*4882a593Smuzhiyun 	struct sadb_x_ipsecrequest *rq;
2556*4882a593Smuzhiyun 	struct xfrm_selector sel;
2557*4882a593Smuzhiyun 	struct xfrm_migrate m[XFRM_MAX_DEPTH];
2558*4882a593Smuzhiyun 	struct xfrm_kmaddress k;
2559*4882a593Smuzhiyun 	struct net *net = sock_net(sk);
2560*4882a593Smuzhiyun 
2561*4882a593Smuzhiyun 	if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC - 1],
2562*4882a593Smuzhiyun 				     ext_hdrs[SADB_EXT_ADDRESS_DST - 1]) ||
2563*4882a593Smuzhiyun 	    !ext_hdrs[SADB_X_EXT_POLICY - 1]) {
2564*4882a593Smuzhiyun 		err = -EINVAL;
2565*4882a593Smuzhiyun 		goto out;
2566*4882a593Smuzhiyun 	}
2567*4882a593Smuzhiyun 
2568*4882a593Smuzhiyun 	kma = ext_hdrs[SADB_X_EXT_KMADDRESS - 1];
2569*4882a593Smuzhiyun 	pol = ext_hdrs[SADB_X_EXT_POLICY - 1];
2570*4882a593Smuzhiyun 
2571*4882a593Smuzhiyun 	if (pol->sadb_x_policy_dir >= IPSEC_DIR_MAX) {
2572*4882a593Smuzhiyun 		err = -EINVAL;
2573*4882a593Smuzhiyun 		goto out;
2574*4882a593Smuzhiyun 	}
2575*4882a593Smuzhiyun 
2576*4882a593Smuzhiyun 	if (kma) {
2577*4882a593Smuzhiyun 		/* convert sadb_x_kmaddress to xfrm_kmaddress */
2578*4882a593Smuzhiyun 		k.reserved = kma->sadb_x_kmaddress_reserved;
2579*4882a593Smuzhiyun 		ret = parse_sockaddr_pair((struct sockaddr *)(kma + 1),
2580*4882a593Smuzhiyun 					  8*(kma->sadb_x_kmaddress_len) - sizeof(*kma),
2581*4882a593Smuzhiyun 					  &k.local, &k.remote, &k.family);
2582*4882a593Smuzhiyun 		if (ret < 0) {
2583*4882a593Smuzhiyun 			err = ret;
2584*4882a593Smuzhiyun 			goto out;
2585*4882a593Smuzhiyun 		}
2586*4882a593Smuzhiyun 	}
2587*4882a593Smuzhiyun 
2588*4882a593Smuzhiyun 	dir = pol->sadb_x_policy_dir - 1;
2589*4882a593Smuzhiyun 	memset(&sel, 0, sizeof(sel));
2590*4882a593Smuzhiyun 
2591*4882a593Smuzhiyun 	/* set source address info of selector */
2592*4882a593Smuzhiyun 	sa = ext_hdrs[SADB_EXT_ADDRESS_SRC - 1];
2593*4882a593Smuzhiyun 	sel.family = pfkey_sadb_addr2xfrm_addr(sa, &sel.saddr);
2594*4882a593Smuzhiyun 	sel.prefixlen_s = sa->sadb_address_prefixlen;
2595*4882a593Smuzhiyun 	sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
2596*4882a593Smuzhiyun 	sel.sport = ((struct sockaddr_in *)(sa + 1))->sin_port;
2597*4882a593Smuzhiyun 	if (sel.sport)
2598*4882a593Smuzhiyun 		sel.sport_mask = htons(0xffff);
2599*4882a593Smuzhiyun 
2600*4882a593Smuzhiyun 	/* set destination address info of selector */
2601*4882a593Smuzhiyun 	sa = ext_hdrs[SADB_EXT_ADDRESS_DST - 1];
2602*4882a593Smuzhiyun 	pfkey_sadb_addr2xfrm_addr(sa, &sel.daddr);
2603*4882a593Smuzhiyun 	sel.prefixlen_d = sa->sadb_address_prefixlen;
2604*4882a593Smuzhiyun 	sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
2605*4882a593Smuzhiyun 	sel.dport = ((struct sockaddr_in *)(sa + 1))->sin_port;
2606*4882a593Smuzhiyun 	if (sel.dport)
2607*4882a593Smuzhiyun 		sel.dport_mask = htons(0xffff);
2608*4882a593Smuzhiyun 
2609*4882a593Smuzhiyun 	rq = (struct sadb_x_ipsecrequest *)(pol + 1);
2610*4882a593Smuzhiyun 
2611*4882a593Smuzhiyun 	/* extract ipsecrequests */
2612*4882a593Smuzhiyun 	i = 0;
2613*4882a593Smuzhiyun 	len = pol->sadb_x_policy_len * 8 - sizeof(struct sadb_x_policy);
2614*4882a593Smuzhiyun 
2615*4882a593Smuzhiyun 	while (len > 0 && i < XFRM_MAX_DEPTH) {
2616*4882a593Smuzhiyun 		ret = ipsecrequests_to_migrate(rq, len, &m[i]);
2617*4882a593Smuzhiyun 		if (ret < 0) {
2618*4882a593Smuzhiyun 			err = ret;
2619*4882a593Smuzhiyun 			goto out;
2620*4882a593Smuzhiyun 		} else {
2621*4882a593Smuzhiyun 			rq = (struct sadb_x_ipsecrequest *)((u8 *)rq + ret);
2622*4882a593Smuzhiyun 			len -= ret;
2623*4882a593Smuzhiyun 			i++;
2624*4882a593Smuzhiyun 		}
2625*4882a593Smuzhiyun 	}
2626*4882a593Smuzhiyun 
2627*4882a593Smuzhiyun 	if (!i || len > 0) {
2628*4882a593Smuzhiyun 		err = -EINVAL;
2629*4882a593Smuzhiyun 		goto out;
2630*4882a593Smuzhiyun 	}
2631*4882a593Smuzhiyun 
2632*4882a593Smuzhiyun 	return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i,
2633*4882a593Smuzhiyun 			    kma ? &k : NULL, net, NULL, 0);
2634*4882a593Smuzhiyun 
2635*4882a593Smuzhiyun  out:
2636*4882a593Smuzhiyun 	return err;
2637*4882a593Smuzhiyun }
2638*4882a593Smuzhiyun #else
pfkey_migrate(struct sock * sk,struct sk_buff * skb,const struct sadb_msg * hdr,void * const * ext_hdrs)2639*4882a593Smuzhiyun static int pfkey_migrate(struct sock *sk, struct sk_buff *skb,
2640*4882a593Smuzhiyun 			 const struct sadb_msg *hdr, void * const *ext_hdrs)
2641*4882a593Smuzhiyun {
2642*4882a593Smuzhiyun 	return -ENOPROTOOPT;
2643*4882a593Smuzhiyun }
2644*4882a593Smuzhiyun #endif
2645*4882a593Smuzhiyun 
2646*4882a593Smuzhiyun 
pfkey_spdget(struct sock * sk,struct sk_buff * skb,const struct sadb_msg * hdr,void * const * ext_hdrs)2647*4882a593Smuzhiyun static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
2648*4882a593Smuzhiyun {
2649*4882a593Smuzhiyun 	struct net *net = sock_net(sk);
2650*4882a593Smuzhiyun 	unsigned int dir;
2651*4882a593Smuzhiyun 	int err = 0, delete;
2652*4882a593Smuzhiyun 	struct sadb_x_policy *pol;
2653*4882a593Smuzhiyun 	struct xfrm_policy *xp;
2654*4882a593Smuzhiyun 	struct km_event c;
2655*4882a593Smuzhiyun 
2656*4882a593Smuzhiyun 	if ((pol = ext_hdrs[SADB_X_EXT_POLICY-1]) == NULL)
2657*4882a593Smuzhiyun 		return -EINVAL;
2658*4882a593Smuzhiyun 
2659*4882a593Smuzhiyun 	dir = xfrm_policy_id2dir(pol->sadb_x_policy_id);
2660*4882a593Smuzhiyun 	if (dir >= XFRM_POLICY_MAX)
2661*4882a593Smuzhiyun 		return -EINVAL;
2662*4882a593Smuzhiyun 
2663*4882a593Smuzhiyun 	delete = (hdr->sadb_msg_type == SADB_X_SPDDELETE2);
2664*4882a593Smuzhiyun 	xp = xfrm_policy_byid(net, &dummy_mark, 0, XFRM_POLICY_TYPE_MAIN,
2665*4882a593Smuzhiyun 			      dir, pol->sadb_x_policy_id, delete, &err);
2666*4882a593Smuzhiyun 	if (xp == NULL)
2667*4882a593Smuzhiyun 		return -ENOENT;
2668*4882a593Smuzhiyun 
2669*4882a593Smuzhiyun 	if (delete) {
2670*4882a593Smuzhiyun 		xfrm_audit_policy_delete(xp, err ? 0 : 1, true);
2671*4882a593Smuzhiyun 
2672*4882a593Smuzhiyun 		if (err)
2673*4882a593Smuzhiyun 			goto out;
2674*4882a593Smuzhiyun 		c.seq = hdr->sadb_msg_seq;
2675*4882a593Smuzhiyun 		c.portid = hdr->sadb_msg_pid;
2676*4882a593Smuzhiyun 		c.data.byid = 1;
2677*4882a593Smuzhiyun 		c.event = XFRM_MSG_DELPOLICY;
2678*4882a593Smuzhiyun 		km_policy_notify(xp, dir, &c);
2679*4882a593Smuzhiyun 	} else {
2680*4882a593Smuzhiyun 		err = key_pol_get_resp(sk, xp, hdr, dir);
2681*4882a593Smuzhiyun 	}
2682*4882a593Smuzhiyun 
2683*4882a593Smuzhiyun out:
2684*4882a593Smuzhiyun 	xfrm_pol_put(xp);
2685*4882a593Smuzhiyun 	return err;
2686*4882a593Smuzhiyun }
2687*4882a593Smuzhiyun 
dump_sp(struct xfrm_policy * xp,int dir,int count,void * ptr)2688*4882a593Smuzhiyun static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
2689*4882a593Smuzhiyun {
2690*4882a593Smuzhiyun 	struct pfkey_sock *pfk = ptr;
2691*4882a593Smuzhiyun 	struct sk_buff *out_skb;
2692*4882a593Smuzhiyun 	struct sadb_msg *out_hdr;
2693*4882a593Smuzhiyun 	int err;
2694*4882a593Smuzhiyun 
2695*4882a593Smuzhiyun 	if (!pfkey_can_dump(&pfk->sk))
2696*4882a593Smuzhiyun 		return -ENOBUFS;
2697*4882a593Smuzhiyun 
2698*4882a593Smuzhiyun 	out_skb = pfkey_xfrm_policy2msg_prep(xp);
2699*4882a593Smuzhiyun 	if (IS_ERR(out_skb))
2700*4882a593Smuzhiyun 		return PTR_ERR(out_skb);
2701*4882a593Smuzhiyun 
2702*4882a593Smuzhiyun 	err = pfkey_xfrm_policy2msg(out_skb, xp, dir);
2703*4882a593Smuzhiyun 	if (err < 0) {
2704*4882a593Smuzhiyun 		kfree_skb(out_skb);
2705*4882a593Smuzhiyun 		return err;
2706*4882a593Smuzhiyun 	}
2707*4882a593Smuzhiyun 
2708*4882a593Smuzhiyun 	out_hdr = (struct sadb_msg *) out_skb->data;
2709*4882a593Smuzhiyun 	out_hdr->sadb_msg_version = pfk->dump.msg_version;
2710*4882a593Smuzhiyun 	out_hdr->sadb_msg_type = SADB_X_SPDDUMP;
2711*4882a593Smuzhiyun 	out_hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC;
2712*4882a593Smuzhiyun 	out_hdr->sadb_msg_errno = 0;
2713*4882a593Smuzhiyun 	out_hdr->sadb_msg_seq = count + 1;
2714*4882a593Smuzhiyun 	out_hdr->sadb_msg_pid = pfk->dump.msg_portid;
2715*4882a593Smuzhiyun 
2716*4882a593Smuzhiyun 	if (pfk->dump.skb)
2717*4882a593Smuzhiyun 		pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
2718*4882a593Smuzhiyun 				&pfk->sk, sock_net(&pfk->sk));
2719*4882a593Smuzhiyun 	pfk->dump.skb = out_skb;
2720*4882a593Smuzhiyun 
2721*4882a593Smuzhiyun 	return 0;
2722*4882a593Smuzhiyun }
2723*4882a593Smuzhiyun 
pfkey_dump_sp(struct pfkey_sock * pfk)2724*4882a593Smuzhiyun static int pfkey_dump_sp(struct pfkey_sock *pfk)
2725*4882a593Smuzhiyun {
2726*4882a593Smuzhiyun 	struct net *net = sock_net(&pfk->sk);
2727*4882a593Smuzhiyun 	return xfrm_policy_walk(net, &pfk->dump.u.policy, dump_sp, (void *) pfk);
2728*4882a593Smuzhiyun }
2729*4882a593Smuzhiyun 
pfkey_dump_sp_done(struct pfkey_sock * pfk)2730*4882a593Smuzhiyun static void pfkey_dump_sp_done(struct pfkey_sock *pfk)
2731*4882a593Smuzhiyun {
2732*4882a593Smuzhiyun 	struct net *net = sock_net((struct sock *)pfk);
2733*4882a593Smuzhiyun 
2734*4882a593Smuzhiyun 	xfrm_policy_walk_done(&pfk->dump.u.policy, net);
2735*4882a593Smuzhiyun }
2736*4882a593Smuzhiyun 
pfkey_spddump(struct sock * sk,struct sk_buff * skb,const struct sadb_msg * hdr,void * const * ext_hdrs)2737*4882a593Smuzhiyun static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
2738*4882a593Smuzhiyun {
2739*4882a593Smuzhiyun 	struct pfkey_sock *pfk = pfkey_sk(sk);
2740*4882a593Smuzhiyun 
2741*4882a593Smuzhiyun 	mutex_lock(&pfk->dump_lock);
2742*4882a593Smuzhiyun 	if (pfk->dump.dump != NULL) {
2743*4882a593Smuzhiyun 		mutex_unlock(&pfk->dump_lock);
2744*4882a593Smuzhiyun 		return -EBUSY;
2745*4882a593Smuzhiyun 	}
2746*4882a593Smuzhiyun 
2747*4882a593Smuzhiyun 	pfk->dump.msg_version = hdr->sadb_msg_version;
2748*4882a593Smuzhiyun 	pfk->dump.msg_portid = hdr->sadb_msg_pid;
2749*4882a593Smuzhiyun 	pfk->dump.dump = pfkey_dump_sp;
2750*4882a593Smuzhiyun 	pfk->dump.done = pfkey_dump_sp_done;
2751*4882a593Smuzhiyun 	xfrm_policy_walk_init(&pfk->dump.u.policy, XFRM_POLICY_TYPE_MAIN);
2752*4882a593Smuzhiyun 	mutex_unlock(&pfk->dump_lock);
2753*4882a593Smuzhiyun 
2754*4882a593Smuzhiyun 	return pfkey_do_dump(pfk);
2755*4882a593Smuzhiyun }
2756*4882a593Smuzhiyun 
key_notify_policy_flush(const struct km_event * c)2757*4882a593Smuzhiyun static int key_notify_policy_flush(const struct km_event *c)
2758*4882a593Smuzhiyun {
2759*4882a593Smuzhiyun 	struct sk_buff *skb_out;
2760*4882a593Smuzhiyun 	struct sadb_msg *hdr;
2761*4882a593Smuzhiyun 
2762*4882a593Smuzhiyun 	skb_out = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_ATOMIC);
2763*4882a593Smuzhiyun 	if (!skb_out)
2764*4882a593Smuzhiyun 		return -ENOBUFS;
2765*4882a593Smuzhiyun 	hdr = skb_put(skb_out, sizeof(struct sadb_msg));
2766*4882a593Smuzhiyun 	hdr->sadb_msg_type = SADB_X_SPDFLUSH;
2767*4882a593Smuzhiyun 	hdr->sadb_msg_seq = c->seq;
2768*4882a593Smuzhiyun 	hdr->sadb_msg_pid = c->portid;
2769*4882a593Smuzhiyun 	hdr->sadb_msg_version = PF_KEY_V2;
2770*4882a593Smuzhiyun 	hdr->sadb_msg_errno = (uint8_t) 0;
2771*4882a593Smuzhiyun 	hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC;
2772*4882a593Smuzhiyun 	hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
2773*4882a593Smuzhiyun 	hdr->sadb_msg_reserved = 0;
2774*4882a593Smuzhiyun 	pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net);
2775*4882a593Smuzhiyun 	return 0;
2776*4882a593Smuzhiyun 
2777*4882a593Smuzhiyun }
2778*4882a593Smuzhiyun 
pfkey_spdflush(struct sock * sk,struct sk_buff * skb,const struct sadb_msg * hdr,void * const * ext_hdrs)2779*4882a593Smuzhiyun static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
2780*4882a593Smuzhiyun {
2781*4882a593Smuzhiyun 	struct net *net = sock_net(sk);
2782*4882a593Smuzhiyun 	struct km_event c;
2783*4882a593Smuzhiyun 	int err, err2;
2784*4882a593Smuzhiyun 
2785*4882a593Smuzhiyun 	err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, true);
2786*4882a593Smuzhiyun 	err2 = unicast_flush_resp(sk, hdr);
2787*4882a593Smuzhiyun 	if (err || err2) {
2788*4882a593Smuzhiyun 		if (err == -ESRCH) /* empty table - old silent behavior */
2789*4882a593Smuzhiyun 			return 0;
2790*4882a593Smuzhiyun 		return err;
2791*4882a593Smuzhiyun 	}
2792*4882a593Smuzhiyun 
2793*4882a593Smuzhiyun 	c.data.type = XFRM_POLICY_TYPE_MAIN;
2794*4882a593Smuzhiyun 	c.event = XFRM_MSG_FLUSHPOLICY;
2795*4882a593Smuzhiyun 	c.portid = hdr->sadb_msg_pid;
2796*4882a593Smuzhiyun 	c.seq = hdr->sadb_msg_seq;
2797*4882a593Smuzhiyun 	c.net = net;
2798*4882a593Smuzhiyun 	km_policy_notify(NULL, 0, &c);
2799*4882a593Smuzhiyun 
2800*4882a593Smuzhiyun 	return 0;
2801*4882a593Smuzhiyun }
2802*4882a593Smuzhiyun 
2803*4882a593Smuzhiyun typedef int (*pfkey_handler)(struct sock *sk, struct sk_buff *skb,
2804*4882a593Smuzhiyun 			     const struct sadb_msg *hdr, void * const *ext_hdrs);
2805*4882a593Smuzhiyun static const pfkey_handler pfkey_funcs[SADB_MAX + 1] = {
2806*4882a593Smuzhiyun 	[SADB_RESERVED]		= pfkey_reserved,
2807*4882a593Smuzhiyun 	[SADB_GETSPI]		= pfkey_getspi,
2808*4882a593Smuzhiyun 	[SADB_UPDATE]		= pfkey_add,
2809*4882a593Smuzhiyun 	[SADB_ADD]		= pfkey_add,
2810*4882a593Smuzhiyun 	[SADB_DELETE]		= pfkey_delete,
2811*4882a593Smuzhiyun 	[SADB_GET]		= pfkey_get,
2812*4882a593Smuzhiyun 	[SADB_ACQUIRE]		= pfkey_acquire,
2813*4882a593Smuzhiyun 	[SADB_REGISTER]		= pfkey_register,
2814*4882a593Smuzhiyun 	[SADB_EXPIRE]		= NULL,
2815*4882a593Smuzhiyun 	[SADB_FLUSH]		= pfkey_flush,
2816*4882a593Smuzhiyun 	[SADB_DUMP]		= pfkey_dump,
2817*4882a593Smuzhiyun 	[SADB_X_PROMISC]	= pfkey_promisc,
2818*4882a593Smuzhiyun 	[SADB_X_PCHANGE]	= NULL,
2819*4882a593Smuzhiyun 	[SADB_X_SPDUPDATE]	= pfkey_spdadd,
2820*4882a593Smuzhiyun 	[SADB_X_SPDADD]		= pfkey_spdadd,
2821*4882a593Smuzhiyun 	[SADB_X_SPDDELETE]	= pfkey_spddelete,
2822*4882a593Smuzhiyun 	[SADB_X_SPDGET]		= pfkey_spdget,
2823*4882a593Smuzhiyun 	[SADB_X_SPDACQUIRE]	= NULL,
2824*4882a593Smuzhiyun 	[SADB_X_SPDDUMP]	= pfkey_spddump,
2825*4882a593Smuzhiyun 	[SADB_X_SPDFLUSH]	= pfkey_spdflush,
2826*4882a593Smuzhiyun 	[SADB_X_SPDSETIDX]	= pfkey_spdadd,
2827*4882a593Smuzhiyun 	[SADB_X_SPDDELETE2]	= pfkey_spdget,
2828*4882a593Smuzhiyun 	[SADB_X_MIGRATE]	= pfkey_migrate,
2829*4882a593Smuzhiyun };
2830*4882a593Smuzhiyun 
pfkey_process(struct sock * sk,struct sk_buff * skb,const struct sadb_msg * hdr)2831*4882a593Smuzhiyun static int pfkey_process(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr)
2832*4882a593Smuzhiyun {
2833*4882a593Smuzhiyun 	void *ext_hdrs[SADB_EXT_MAX];
2834*4882a593Smuzhiyun 	int err;
2835*4882a593Smuzhiyun 
2836*4882a593Smuzhiyun 	/* Non-zero return value of pfkey_broadcast() does not always signal
2837*4882a593Smuzhiyun 	 * an error and even on an actual error we may still want to process
2838*4882a593Smuzhiyun 	 * the message so rather ignore the return value.
2839*4882a593Smuzhiyun 	 */
2840*4882a593Smuzhiyun 	pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL,
2841*4882a593Smuzhiyun 			BROADCAST_PROMISC_ONLY, NULL, sock_net(sk));
2842*4882a593Smuzhiyun 
2843*4882a593Smuzhiyun 	memset(ext_hdrs, 0, sizeof(ext_hdrs));
2844*4882a593Smuzhiyun 	err = parse_exthdrs(skb, hdr, ext_hdrs);
2845*4882a593Smuzhiyun 	if (!err) {
2846*4882a593Smuzhiyun 		err = -EOPNOTSUPP;
2847*4882a593Smuzhiyun 		if (pfkey_funcs[hdr->sadb_msg_type])
2848*4882a593Smuzhiyun 			err = pfkey_funcs[hdr->sadb_msg_type](sk, skb, hdr, ext_hdrs);
2849*4882a593Smuzhiyun 	}
2850*4882a593Smuzhiyun 	return err;
2851*4882a593Smuzhiyun }
2852*4882a593Smuzhiyun 
pfkey_get_base_msg(struct sk_buff * skb,int * errp)2853*4882a593Smuzhiyun static struct sadb_msg *pfkey_get_base_msg(struct sk_buff *skb, int *errp)
2854*4882a593Smuzhiyun {
2855*4882a593Smuzhiyun 	struct sadb_msg *hdr = NULL;
2856*4882a593Smuzhiyun 
2857*4882a593Smuzhiyun 	if (skb->len < sizeof(*hdr)) {
2858*4882a593Smuzhiyun 		*errp = -EMSGSIZE;
2859*4882a593Smuzhiyun 	} else {
2860*4882a593Smuzhiyun 		hdr = (struct sadb_msg *) skb->data;
2861*4882a593Smuzhiyun 		if (hdr->sadb_msg_version != PF_KEY_V2 ||
2862*4882a593Smuzhiyun 		    hdr->sadb_msg_reserved != 0 ||
2863*4882a593Smuzhiyun 		    (hdr->sadb_msg_type <= SADB_RESERVED ||
2864*4882a593Smuzhiyun 		     hdr->sadb_msg_type > SADB_MAX)) {
2865*4882a593Smuzhiyun 			hdr = NULL;
2866*4882a593Smuzhiyun 			*errp = -EINVAL;
2867*4882a593Smuzhiyun 		} else if (hdr->sadb_msg_len != (skb->len /
2868*4882a593Smuzhiyun 						 sizeof(uint64_t)) ||
2869*4882a593Smuzhiyun 			   hdr->sadb_msg_len < (sizeof(struct sadb_msg) /
2870*4882a593Smuzhiyun 						sizeof(uint64_t))) {
2871*4882a593Smuzhiyun 			hdr = NULL;
2872*4882a593Smuzhiyun 			*errp = -EMSGSIZE;
2873*4882a593Smuzhiyun 		} else {
2874*4882a593Smuzhiyun 			*errp = 0;
2875*4882a593Smuzhiyun 		}
2876*4882a593Smuzhiyun 	}
2877*4882a593Smuzhiyun 	return hdr;
2878*4882a593Smuzhiyun }
2879*4882a593Smuzhiyun 
aalg_tmpl_set(const struct xfrm_tmpl * t,const struct xfrm_algo_desc * d)2880*4882a593Smuzhiyun static inline int aalg_tmpl_set(const struct xfrm_tmpl *t,
2881*4882a593Smuzhiyun 				const struct xfrm_algo_desc *d)
2882*4882a593Smuzhiyun {
2883*4882a593Smuzhiyun 	unsigned int id = d->desc.sadb_alg_id;
2884*4882a593Smuzhiyun 
2885*4882a593Smuzhiyun 	if (id >= sizeof(t->aalgos) * 8)
2886*4882a593Smuzhiyun 		return 0;
2887*4882a593Smuzhiyun 
2888*4882a593Smuzhiyun 	return (t->aalgos >> id) & 1;
2889*4882a593Smuzhiyun }
2890*4882a593Smuzhiyun 
ealg_tmpl_set(const struct xfrm_tmpl * t,const struct xfrm_algo_desc * d)2891*4882a593Smuzhiyun static inline int ealg_tmpl_set(const struct xfrm_tmpl *t,
2892*4882a593Smuzhiyun 				const struct xfrm_algo_desc *d)
2893*4882a593Smuzhiyun {
2894*4882a593Smuzhiyun 	unsigned int id = d->desc.sadb_alg_id;
2895*4882a593Smuzhiyun 
2896*4882a593Smuzhiyun 	if (id >= sizeof(t->ealgos) * 8)
2897*4882a593Smuzhiyun 		return 0;
2898*4882a593Smuzhiyun 
2899*4882a593Smuzhiyun 	return (t->ealgos >> id) & 1;
2900*4882a593Smuzhiyun }
2901*4882a593Smuzhiyun 
count_ah_combs(const struct xfrm_tmpl * t)2902*4882a593Smuzhiyun static int count_ah_combs(const struct xfrm_tmpl *t)
2903*4882a593Smuzhiyun {
2904*4882a593Smuzhiyun 	int i, sz = 0;
2905*4882a593Smuzhiyun 
2906*4882a593Smuzhiyun 	for (i = 0; ; i++) {
2907*4882a593Smuzhiyun 		const struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(i);
2908*4882a593Smuzhiyun 		if (!aalg)
2909*4882a593Smuzhiyun 			break;
2910*4882a593Smuzhiyun 		if (!aalg->pfkey_supported)
2911*4882a593Smuzhiyun 			continue;
2912*4882a593Smuzhiyun 		if (aalg_tmpl_set(t, aalg))
2913*4882a593Smuzhiyun 			sz += sizeof(struct sadb_comb);
2914*4882a593Smuzhiyun 	}
2915*4882a593Smuzhiyun 	return sz + sizeof(struct sadb_prop);
2916*4882a593Smuzhiyun }
2917*4882a593Smuzhiyun 
count_esp_combs(const struct xfrm_tmpl * t)2918*4882a593Smuzhiyun static int count_esp_combs(const struct xfrm_tmpl *t)
2919*4882a593Smuzhiyun {
2920*4882a593Smuzhiyun 	int i, k, sz = 0;
2921*4882a593Smuzhiyun 
2922*4882a593Smuzhiyun 	for (i = 0; ; i++) {
2923*4882a593Smuzhiyun 		const struct xfrm_algo_desc *ealg = xfrm_ealg_get_byidx(i);
2924*4882a593Smuzhiyun 		if (!ealg)
2925*4882a593Smuzhiyun 			break;
2926*4882a593Smuzhiyun 
2927*4882a593Smuzhiyun 		if (!ealg->pfkey_supported)
2928*4882a593Smuzhiyun 			continue;
2929*4882a593Smuzhiyun 
2930*4882a593Smuzhiyun 		if (!(ealg_tmpl_set(t, ealg)))
2931*4882a593Smuzhiyun 			continue;
2932*4882a593Smuzhiyun 
2933*4882a593Smuzhiyun 		for (k = 1; ; k++) {
2934*4882a593Smuzhiyun 			const struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(k);
2935*4882a593Smuzhiyun 			if (!aalg)
2936*4882a593Smuzhiyun 				break;
2937*4882a593Smuzhiyun 
2938*4882a593Smuzhiyun 			if (!aalg->pfkey_supported)
2939*4882a593Smuzhiyun 				continue;
2940*4882a593Smuzhiyun 
2941*4882a593Smuzhiyun 			if (aalg_tmpl_set(t, aalg))
2942*4882a593Smuzhiyun 				sz += sizeof(struct sadb_comb);
2943*4882a593Smuzhiyun 		}
2944*4882a593Smuzhiyun 	}
2945*4882a593Smuzhiyun 	return sz + sizeof(struct sadb_prop);
2946*4882a593Smuzhiyun }
2947*4882a593Smuzhiyun 
dump_ah_combs(struct sk_buff * skb,const struct xfrm_tmpl * t)2948*4882a593Smuzhiyun static int dump_ah_combs(struct sk_buff *skb, const struct xfrm_tmpl *t)
2949*4882a593Smuzhiyun {
2950*4882a593Smuzhiyun 	struct sadb_prop *p;
2951*4882a593Smuzhiyun 	int sz = 0;
2952*4882a593Smuzhiyun 	int i;
2953*4882a593Smuzhiyun 
2954*4882a593Smuzhiyun 	p = skb_put(skb, sizeof(struct sadb_prop));
2955*4882a593Smuzhiyun 	p->sadb_prop_len = sizeof(struct sadb_prop)/8;
2956*4882a593Smuzhiyun 	p->sadb_prop_exttype = SADB_EXT_PROPOSAL;
2957*4882a593Smuzhiyun 	p->sadb_prop_replay = 32;
2958*4882a593Smuzhiyun 	memset(p->sadb_prop_reserved, 0, sizeof(p->sadb_prop_reserved));
2959*4882a593Smuzhiyun 
2960*4882a593Smuzhiyun 	for (i = 0; ; i++) {
2961*4882a593Smuzhiyun 		const struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(i);
2962*4882a593Smuzhiyun 		if (!aalg)
2963*4882a593Smuzhiyun 			break;
2964*4882a593Smuzhiyun 
2965*4882a593Smuzhiyun 		if (!aalg->pfkey_supported)
2966*4882a593Smuzhiyun 			continue;
2967*4882a593Smuzhiyun 
2968*4882a593Smuzhiyun 		if (aalg_tmpl_set(t, aalg) && aalg->available) {
2969*4882a593Smuzhiyun 			struct sadb_comb *c;
2970*4882a593Smuzhiyun 			c = skb_put_zero(skb, sizeof(struct sadb_comb));
2971*4882a593Smuzhiyun 			p->sadb_prop_len += sizeof(struct sadb_comb)/8;
2972*4882a593Smuzhiyun 			c->sadb_comb_auth = aalg->desc.sadb_alg_id;
2973*4882a593Smuzhiyun 			c->sadb_comb_auth_minbits = aalg->desc.sadb_alg_minbits;
2974*4882a593Smuzhiyun 			c->sadb_comb_auth_maxbits = aalg->desc.sadb_alg_maxbits;
2975*4882a593Smuzhiyun 			c->sadb_comb_hard_addtime = 24*60*60;
2976*4882a593Smuzhiyun 			c->sadb_comb_soft_addtime = 20*60*60;
2977*4882a593Smuzhiyun 			c->sadb_comb_hard_usetime = 8*60*60;
2978*4882a593Smuzhiyun 			c->sadb_comb_soft_usetime = 7*60*60;
2979*4882a593Smuzhiyun 			sz += sizeof(*c);
2980*4882a593Smuzhiyun 		}
2981*4882a593Smuzhiyun 	}
2982*4882a593Smuzhiyun 
2983*4882a593Smuzhiyun 	return sz + sizeof(*p);
2984*4882a593Smuzhiyun }
2985*4882a593Smuzhiyun 
dump_esp_combs(struct sk_buff * skb,const struct xfrm_tmpl * t)2986*4882a593Smuzhiyun static int dump_esp_combs(struct sk_buff *skb, const struct xfrm_tmpl *t)
2987*4882a593Smuzhiyun {
2988*4882a593Smuzhiyun 	struct sadb_prop *p;
2989*4882a593Smuzhiyun 	int sz = 0;
2990*4882a593Smuzhiyun 	int i, k;
2991*4882a593Smuzhiyun 
2992*4882a593Smuzhiyun 	p = skb_put(skb, sizeof(struct sadb_prop));
2993*4882a593Smuzhiyun 	p->sadb_prop_len = sizeof(struct sadb_prop)/8;
2994*4882a593Smuzhiyun 	p->sadb_prop_exttype = SADB_EXT_PROPOSAL;
2995*4882a593Smuzhiyun 	p->sadb_prop_replay = 32;
2996*4882a593Smuzhiyun 	memset(p->sadb_prop_reserved, 0, sizeof(p->sadb_prop_reserved));
2997*4882a593Smuzhiyun 
2998*4882a593Smuzhiyun 	for (i=0; ; i++) {
2999*4882a593Smuzhiyun 		const struct xfrm_algo_desc *ealg = xfrm_ealg_get_byidx(i);
3000*4882a593Smuzhiyun 		if (!ealg)
3001*4882a593Smuzhiyun 			break;
3002*4882a593Smuzhiyun 
3003*4882a593Smuzhiyun 		if (!ealg->pfkey_supported)
3004*4882a593Smuzhiyun 			continue;
3005*4882a593Smuzhiyun 
3006*4882a593Smuzhiyun 		if (!(ealg_tmpl_set(t, ealg) && ealg->available))
3007*4882a593Smuzhiyun 			continue;
3008*4882a593Smuzhiyun 
3009*4882a593Smuzhiyun 		for (k = 1; ; k++) {
3010*4882a593Smuzhiyun 			struct sadb_comb *c;
3011*4882a593Smuzhiyun 			const struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(k);
3012*4882a593Smuzhiyun 			if (!aalg)
3013*4882a593Smuzhiyun 				break;
3014*4882a593Smuzhiyun 			if (!aalg->pfkey_supported)
3015*4882a593Smuzhiyun 				continue;
3016*4882a593Smuzhiyun 			if (!(aalg_tmpl_set(t, aalg) && aalg->available))
3017*4882a593Smuzhiyun 				continue;
3018*4882a593Smuzhiyun 			c = skb_put(skb, sizeof(struct sadb_comb));
3019*4882a593Smuzhiyun 			memset(c, 0, sizeof(*c));
3020*4882a593Smuzhiyun 			p->sadb_prop_len += sizeof(struct sadb_comb)/8;
3021*4882a593Smuzhiyun 			c->sadb_comb_auth = aalg->desc.sadb_alg_id;
3022*4882a593Smuzhiyun 			c->sadb_comb_auth_minbits = aalg->desc.sadb_alg_minbits;
3023*4882a593Smuzhiyun 			c->sadb_comb_auth_maxbits = aalg->desc.sadb_alg_maxbits;
3024*4882a593Smuzhiyun 			c->sadb_comb_encrypt = ealg->desc.sadb_alg_id;
3025*4882a593Smuzhiyun 			c->sadb_comb_encrypt_minbits = ealg->desc.sadb_alg_minbits;
3026*4882a593Smuzhiyun 			c->sadb_comb_encrypt_maxbits = ealg->desc.sadb_alg_maxbits;
3027*4882a593Smuzhiyun 			c->sadb_comb_hard_addtime = 24*60*60;
3028*4882a593Smuzhiyun 			c->sadb_comb_soft_addtime = 20*60*60;
3029*4882a593Smuzhiyun 			c->sadb_comb_hard_usetime = 8*60*60;
3030*4882a593Smuzhiyun 			c->sadb_comb_soft_usetime = 7*60*60;
3031*4882a593Smuzhiyun 			sz += sizeof(*c);
3032*4882a593Smuzhiyun 		}
3033*4882a593Smuzhiyun 	}
3034*4882a593Smuzhiyun 
3035*4882a593Smuzhiyun 	return sz + sizeof(*p);
3036*4882a593Smuzhiyun }
3037*4882a593Smuzhiyun 
key_notify_policy_expire(struct xfrm_policy * xp,const struct km_event * c)3038*4882a593Smuzhiyun static int key_notify_policy_expire(struct xfrm_policy *xp, const struct km_event *c)
3039*4882a593Smuzhiyun {
3040*4882a593Smuzhiyun 	return 0;
3041*4882a593Smuzhiyun }
3042*4882a593Smuzhiyun 
key_notify_sa_expire(struct xfrm_state * x,const struct km_event * c)3043*4882a593Smuzhiyun static int key_notify_sa_expire(struct xfrm_state *x, const struct km_event *c)
3044*4882a593Smuzhiyun {
3045*4882a593Smuzhiyun 	struct sk_buff *out_skb;
3046*4882a593Smuzhiyun 	struct sadb_msg *out_hdr;
3047*4882a593Smuzhiyun 	int hard;
3048*4882a593Smuzhiyun 	int hsc;
3049*4882a593Smuzhiyun 
3050*4882a593Smuzhiyun 	hard = c->data.hard;
3051*4882a593Smuzhiyun 	if (hard)
3052*4882a593Smuzhiyun 		hsc = 2;
3053*4882a593Smuzhiyun 	else
3054*4882a593Smuzhiyun 		hsc = 1;
3055*4882a593Smuzhiyun 
3056*4882a593Smuzhiyun 	out_skb = pfkey_xfrm_state2msg_expire(x, hsc);
3057*4882a593Smuzhiyun 	if (IS_ERR(out_skb))
3058*4882a593Smuzhiyun 		return PTR_ERR(out_skb);
3059*4882a593Smuzhiyun 
3060*4882a593Smuzhiyun 	out_hdr = (struct sadb_msg *) out_skb->data;
3061*4882a593Smuzhiyun 	out_hdr->sadb_msg_version = PF_KEY_V2;
3062*4882a593Smuzhiyun 	out_hdr->sadb_msg_type = SADB_EXPIRE;
3063*4882a593Smuzhiyun 	out_hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto);
3064*4882a593Smuzhiyun 	out_hdr->sadb_msg_errno = 0;
3065*4882a593Smuzhiyun 	out_hdr->sadb_msg_reserved = 0;
3066*4882a593Smuzhiyun 	out_hdr->sadb_msg_seq = 0;
3067*4882a593Smuzhiyun 	out_hdr->sadb_msg_pid = 0;
3068*4882a593Smuzhiyun 
3069*4882a593Smuzhiyun 	pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL,
3070*4882a593Smuzhiyun 			xs_net(x));
3071*4882a593Smuzhiyun 	return 0;
3072*4882a593Smuzhiyun }
3073*4882a593Smuzhiyun 
pfkey_send_notify(struct xfrm_state * x,const struct km_event * c)3074*4882a593Smuzhiyun static int pfkey_send_notify(struct xfrm_state *x, const struct km_event *c)
3075*4882a593Smuzhiyun {
3076*4882a593Smuzhiyun 	struct net *net = x ? xs_net(x) : c->net;
3077*4882a593Smuzhiyun 	struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
3078*4882a593Smuzhiyun 
3079*4882a593Smuzhiyun 	if (atomic_read(&net_pfkey->socks_nr) == 0)
3080*4882a593Smuzhiyun 		return 0;
3081*4882a593Smuzhiyun 
3082*4882a593Smuzhiyun 	switch (c->event) {
3083*4882a593Smuzhiyun 	case XFRM_MSG_EXPIRE:
3084*4882a593Smuzhiyun 		return key_notify_sa_expire(x, c);
3085*4882a593Smuzhiyun 	case XFRM_MSG_DELSA:
3086*4882a593Smuzhiyun 	case XFRM_MSG_NEWSA:
3087*4882a593Smuzhiyun 	case XFRM_MSG_UPDSA:
3088*4882a593Smuzhiyun 		return key_notify_sa(x, c);
3089*4882a593Smuzhiyun 	case XFRM_MSG_FLUSHSA:
3090*4882a593Smuzhiyun 		return key_notify_sa_flush(c);
3091*4882a593Smuzhiyun 	case XFRM_MSG_NEWAE: /* not yet supported */
3092*4882a593Smuzhiyun 		break;
3093*4882a593Smuzhiyun 	default:
3094*4882a593Smuzhiyun 		pr_err("pfkey: Unknown SA event %d\n", c->event);
3095*4882a593Smuzhiyun 		break;
3096*4882a593Smuzhiyun 	}
3097*4882a593Smuzhiyun 
3098*4882a593Smuzhiyun 	return 0;
3099*4882a593Smuzhiyun }
3100*4882a593Smuzhiyun 
pfkey_send_policy_notify(struct xfrm_policy * xp,int dir,const struct km_event * c)3101*4882a593Smuzhiyun static int pfkey_send_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c)
3102*4882a593Smuzhiyun {
3103*4882a593Smuzhiyun 	if (xp && xp->type != XFRM_POLICY_TYPE_MAIN)
3104*4882a593Smuzhiyun 		return 0;
3105*4882a593Smuzhiyun 
3106*4882a593Smuzhiyun 	switch (c->event) {
3107*4882a593Smuzhiyun 	case XFRM_MSG_POLEXPIRE:
3108*4882a593Smuzhiyun 		return key_notify_policy_expire(xp, c);
3109*4882a593Smuzhiyun 	case XFRM_MSG_DELPOLICY:
3110*4882a593Smuzhiyun 	case XFRM_MSG_NEWPOLICY:
3111*4882a593Smuzhiyun 	case XFRM_MSG_UPDPOLICY:
3112*4882a593Smuzhiyun 		return key_notify_policy(xp, dir, c);
3113*4882a593Smuzhiyun 	case XFRM_MSG_FLUSHPOLICY:
3114*4882a593Smuzhiyun 		if (c->data.type != XFRM_POLICY_TYPE_MAIN)
3115*4882a593Smuzhiyun 			break;
3116*4882a593Smuzhiyun 		return key_notify_policy_flush(c);
3117*4882a593Smuzhiyun 	default:
3118*4882a593Smuzhiyun 		pr_err("pfkey: Unknown policy event %d\n", c->event);
3119*4882a593Smuzhiyun 		break;
3120*4882a593Smuzhiyun 	}
3121*4882a593Smuzhiyun 
3122*4882a593Smuzhiyun 	return 0;
3123*4882a593Smuzhiyun }
3124*4882a593Smuzhiyun 
get_acqseq(void)3125*4882a593Smuzhiyun static u32 get_acqseq(void)
3126*4882a593Smuzhiyun {
3127*4882a593Smuzhiyun 	u32 res;
3128*4882a593Smuzhiyun 	static atomic_t acqseq;
3129*4882a593Smuzhiyun 
3130*4882a593Smuzhiyun 	do {
3131*4882a593Smuzhiyun 		res = atomic_inc_return(&acqseq);
3132*4882a593Smuzhiyun 	} while (!res);
3133*4882a593Smuzhiyun 	return res;
3134*4882a593Smuzhiyun }
3135*4882a593Smuzhiyun 
pfkey_is_alive(const struct km_event * c)3136*4882a593Smuzhiyun static bool pfkey_is_alive(const struct km_event *c)
3137*4882a593Smuzhiyun {
3138*4882a593Smuzhiyun 	struct netns_pfkey *net_pfkey = net_generic(c->net, pfkey_net_id);
3139*4882a593Smuzhiyun 	struct sock *sk;
3140*4882a593Smuzhiyun 	bool is_alive = false;
3141*4882a593Smuzhiyun 
3142*4882a593Smuzhiyun 	rcu_read_lock();
3143*4882a593Smuzhiyun 	sk_for_each_rcu(sk, &net_pfkey->table) {
3144*4882a593Smuzhiyun 		if (pfkey_sk(sk)->registered) {
3145*4882a593Smuzhiyun 			is_alive = true;
3146*4882a593Smuzhiyun 			break;
3147*4882a593Smuzhiyun 		}
3148*4882a593Smuzhiyun 	}
3149*4882a593Smuzhiyun 	rcu_read_unlock();
3150*4882a593Smuzhiyun 
3151*4882a593Smuzhiyun 	return is_alive;
3152*4882a593Smuzhiyun }
3153*4882a593Smuzhiyun 
pfkey_send_acquire(struct xfrm_state * x,struct xfrm_tmpl * t,struct xfrm_policy * xp)3154*4882a593Smuzhiyun static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *xp)
3155*4882a593Smuzhiyun {
3156*4882a593Smuzhiyun 	struct sk_buff *skb;
3157*4882a593Smuzhiyun 	struct sadb_msg *hdr;
3158*4882a593Smuzhiyun 	struct sadb_address *addr;
3159*4882a593Smuzhiyun 	struct sadb_x_policy *pol;
3160*4882a593Smuzhiyun 	int sockaddr_size;
3161*4882a593Smuzhiyun 	int size;
3162*4882a593Smuzhiyun 	struct sadb_x_sec_ctx *sec_ctx;
3163*4882a593Smuzhiyun 	struct xfrm_sec_ctx *xfrm_ctx;
3164*4882a593Smuzhiyun 	int ctx_size = 0;
3165*4882a593Smuzhiyun 	int alg_size = 0;
3166*4882a593Smuzhiyun 
3167*4882a593Smuzhiyun 	sockaddr_size = pfkey_sockaddr_size(x->props.family);
3168*4882a593Smuzhiyun 	if (!sockaddr_size)
3169*4882a593Smuzhiyun 		return -EINVAL;
3170*4882a593Smuzhiyun 
3171*4882a593Smuzhiyun 	size = sizeof(struct sadb_msg) +
3172*4882a593Smuzhiyun 		(sizeof(struct sadb_address) * 2) +
3173*4882a593Smuzhiyun 		(sockaddr_size * 2) +
3174*4882a593Smuzhiyun 		sizeof(struct sadb_x_policy);
3175*4882a593Smuzhiyun 
3176*4882a593Smuzhiyun 	if (x->id.proto == IPPROTO_AH)
3177*4882a593Smuzhiyun 		alg_size = count_ah_combs(t);
3178*4882a593Smuzhiyun 	else if (x->id.proto == IPPROTO_ESP)
3179*4882a593Smuzhiyun 		alg_size = count_esp_combs(t);
3180*4882a593Smuzhiyun 
3181*4882a593Smuzhiyun 	if ((xfrm_ctx = x->security)) {
3182*4882a593Smuzhiyun 		ctx_size = PFKEY_ALIGN8(xfrm_ctx->ctx_len);
3183*4882a593Smuzhiyun 		size +=  sizeof(struct sadb_x_sec_ctx) + ctx_size;
3184*4882a593Smuzhiyun 	}
3185*4882a593Smuzhiyun 
3186*4882a593Smuzhiyun 	skb =  alloc_skb(size + alg_size + 16, GFP_ATOMIC);
3187*4882a593Smuzhiyun 	if (skb == NULL)
3188*4882a593Smuzhiyun 		return -ENOMEM;
3189*4882a593Smuzhiyun 
3190*4882a593Smuzhiyun 	hdr = skb_put(skb, sizeof(struct sadb_msg));
3191*4882a593Smuzhiyun 	hdr->sadb_msg_version = PF_KEY_V2;
3192*4882a593Smuzhiyun 	hdr->sadb_msg_type = SADB_ACQUIRE;
3193*4882a593Smuzhiyun 	hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto);
3194*4882a593Smuzhiyun 	hdr->sadb_msg_len = size / sizeof(uint64_t);
3195*4882a593Smuzhiyun 	hdr->sadb_msg_errno = 0;
3196*4882a593Smuzhiyun 	hdr->sadb_msg_reserved = 0;
3197*4882a593Smuzhiyun 	hdr->sadb_msg_seq = x->km.seq = get_acqseq();
3198*4882a593Smuzhiyun 	hdr->sadb_msg_pid = 0;
3199*4882a593Smuzhiyun 
3200*4882a593Smuzhiyun 	/* src address */
3201*4882a593Smuzhiyun 	addr = skb_put(skb, sizeof(struct sadb_address) + sockaddr_size);
3202*4882a593Smuzhiyun 	addr->sadb_address_len =
3203*4882a593Smuzhiyun 		(sizeof(struct sadb_address)+sockaddr_size)/
3204*4882a593Smuzhiyun 			sizeof(uint64_t);
3205*4882a593Smuzhiyun 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
3206*4882a593Smuzhiyun 	addr->sadb_address_proto = 0;
3207*4882a593Smuzhiyun 	addr->sadb_address_reserved = 0;
3208*4882a593Smuzhiyun 	addr->sadb_address_prefixlen =
3209*4882a593Smuzhiyun 		pfkey_sockaddr_fill(&x->props.saddr, 0,
3210*4882a593Smuzhiyun 				    (struct sockaddr *) (addr + 1),
3211*4882a593Smuzhiyun 				    x->props.family);
3212*4882a593Smuzhiyun 	if (!addr->sadb_address_prefixlen)
3213*4882a593Smuzhiyun 		BUG();
3214*4882a593Smuzhiyun 
3215*4882a593Smuzhiyun 	/* dst address */
3216*4882a593Smuzhiyun 	addr = skb_put(skb, sizeof(struct sadb_address) + sockaddr_size);
3217*4882a593Smuzhiyun 	addr->sadb_address_len =
3218*4882a593Smuzhiyun 		(sizeof(struct sadb_address)+sockaddr_size)/
3219*4882a593Smuzhiyun 			sizeof(uint64_t);
3220*4882a593Smuzhiyun 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
3221*4882a593Smuzhiyun 	addr->sadb_address_proto = 0;
3222*4882a593Smuzhiyun 	addr->sadb_address_reserved = 0;
3223*4882a593Smuzhiyun 	addr->sadb_address_prefixlen =
3224*4882a593Smuzhiyun 		pfkey_sockaddr_fill(&x->id.daddr, 0,
3225*4882a593Smuzhiyun 				    (struct sockaddr *) (addr + 1),
3226*4882a593Smuzhiyun 				    x->props.family);
3227*4882a593Smuzhiyun 	if (!addr->sadb_address_prefixlen)
3228*4882a593Smuzhiyun 		BUG();
3229*4882a593Smuzhiyun 
3230*4882a593Smuzhiyun 	pol = skb_put(skb, sizeof(struct sadb_x_policy));
3231*4882a593Smuzhiyun 	pol->sadb_x_policy_len = sizeof(struct sadb_x_policy)/sizeof(uint64_t);
3232*4882a593Smuzhiyun 	pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
3233*4882a593Smuzhiyun 	pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
3234*4882a593Smuzhiyun 	pol->sadb_x_policy_dir = XFRM_POLICY_OUT + 1;
3235*4882a593Smuzhiyun 	pol->sadb_x_policy_reserved = 0;
3236*4882a593Smuzhiyun 	pol->sadb_x_policy_id = xp->index;
3237*4882a593Smuzhiyun 	pol->sadb_x_policy_priority = xp->priority;
3238*4882a593Smuzhiyun 
3239*4882a593Smuzhiyun 	/* Set sadb_comb's. */
3240*4882a593Smuzhiyun 	alg_size = 0;
3241*4882a593Smuzhiyun 	if (x->id.proto == IPPROTO_AH)
3242*4882a593Smuzhiyun 		alg_size = dump_ah_combs(skb, t);
3243*4882a593Smuzhiyun 	else if (x->id.proto == IPPROTO_ESP)
3244*4882a593Smuzhiyun 		alg_size = dump_esp_combs(skb, t);
3245*4882a593Smuzhiyun 
3246*4882a593Smuzhiyun 	hdr->sadb_msg_len += alg_size / 8;
3247*4882a593Smuzhiyun 
3248*4882a593Smuzhiyun 	/* security context */
3249*4882a593Smuzhiyun 	if (xfrm_ctx) {
3250*4882a593Smuzhiyun 		sec_ctx = skb_put(skb,
3251*4882a593Smuzhiyun 				  sizeof(struct sadb_x_sec_ctx) + ctx_size);
3252*4882a593Smuzhiyun 		sec_ctx->sadb_x_sec_len =
3253*4882a593Smuzhiyun 		  (sizeof(struct sadb_x_sec_ctx) + ctx_size) / sizeof(uint64_t);
3254*4882a593Smuzhiyun 		sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
3255*4882a593Smuzhiyun 		sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi;
3256*4882a593Smuzhiyun 		sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg;
3257*4882a593Smuzhiyun 		sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len;
3258*4882a593Smuzhiyun 		memcpy(sec_ctx + 1, xfrm_ctx->ctx_str,
3259*4882a593Smuzhiyun 		       xfrm_ctx->ctx_len);
3260*4882a593Smuzhiyun 	}
3261*4882a593Smuzhiyun 
3262*4882a593Smuzhiyun 	return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL,
3263*4882a593Smuzhiyun 			       xs_net(x));
3264*4882a593Smuzhiyun }
3265*4882a593Smuzhiyun 
pfkey_compile_policy(struct sock * sk,int opt,u8 * data,int len,int * dir)3266*4882a593Smuzhiyun static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
3267*4882a593Smuzhiyun 						u8 *data, int len, int *dir)
3268*4882a593Smuzhiyun {
3269*4882a593Smuzhiyun 	struct net *net = sock_net(sk);
3270*4882a593Smuzhiyun 	struct xfrm_policy *xp;
3271*4882a593Smuzhiyun 	struct sadb_x_policy *pol = (struct sadb_x_policy*)data;
3272*4882a593Smuzhiyun 	struct sadb_x_sec_ctx *sec_ctx;
3273*4882a593Smuzhiyun 
3274*4882a593Smuzhiyun 	switch (sk->sk_family) {
3275*4882a593Smuzhiyun 	case AF_INET:
3276*4882a593Smuzhiyun 		if (opt != IP_IPSEC_POLICY) {
3277*4882a593Smuzhiyun 			*dir = -EOPNOTSUPP;
3278*4882a593Smuzhiyun 			return NULL;
3279*4882a593Smuzhiyun 		}
3280*4882a593Smuzhiyun 		break;
3281*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
3282*4882a593Smuzhiyun 	case AF_INET6:
3283*4882a593Smuzhiyun 		if (opt != IPV6_IPSEC_POLICY) {
3284*4882a593Smuzhiyun 			*dir = -EOPNOTSUPP;
3285*4882a593Smuzhiyun 			return NULL;
3286*4882a593Smuzhiyun 		}
3287*4882a593Smuzhiyun 		break;
3288*4882a593Smuzhiyun #endif
3289*4882a593Smuzhiyun 	default:
3290*4882a593Smuzhiyun 		*dir = -EINVAL;
3291*4882a593Smuzhiyun 		return NULL;
3292*4882a593Smuzhiyun 	}
3293*4882a593Smuzhiyun 
3294*4882a593Smuzhiyun 	*dir = -EINVAL;
3295*4882a593Smuzhiyun 
3296*4882a593Smuzhiyun 	if (len < sizeof(struct sadb_x_policy) ||
3297*4882a593Smuzhiyun 	    pol->sadb_x_policy_len*8 > len ||
3298*4882a593Smuzhiyun 	    pol->sadb_x_policy_type > IPSEC_POLICY_BYPASS ||
3299*4882a593Smuzhiyun 	    (!pol->sadb_x_policy_dir || pol->sadb_x_policy_dir > IPSEC_DIR_OUTBOUND))
3300*4882a593Smuzhiyun 		return NULL;
3301*4882a593Smuzhiyun 
3302*4882a593Smuzhiyun 	xp = xfrm_policy_alloc(net, GFP_ATOMIC);
3303*4882a593Smuzhiyun 	if (xp == NULL) {
3304*4882a593Smuzhiyun 		*dir = -ENOBUFS;
3305*4882a593Smuzhiyun 		return NULL;
3306*4882a593Smuzhiyun 	}
3307*4882a593Smuzhiyun 
3308*4882a593Smuzhiyun 	xp->action = (pol->sadb_x_policy_type == IPSEC_POLICY_DISCARD ?
3309*4882a593Smuzhiyun 		      XFRM_POLICY_BLOCK : XFRM_POLICY_ALLOW);
3310*4882a593Smuzhiyun 
3311*4882a593Smuzhiyun 	xp->lft.soft_byte_limit = XFRM_INF;
3312*4882a593Smuzhiyun 	xp->lft.hard_byte_limit = XFRM_INF;
3313*4882a593Smuzhiyun 	xp->lft.soft_packet_limit = XFRM_INF;
3314*4882a593Smuzhiyun 	xp->lft.hard_packet_limit = XFRM_INF;
3315*4882a593Smuzhiyun 	xp->family = sk->sk_family;
3316*4882a593Smuzhiyun 
3317*4882a593Smuzhiyun 	xp->xfrm_nr = 0;
3318*4882a593Smuzhiyun 	if (pol->sadb_x_policy_type == IPSEC_POLICY_IPSEC &&
3319*4882a593Smuzhiyun 	    (*dir = parse_ipsecrequests(xp, pol)) < 0)
3320*4882a593Smuzhiyun 		goto out;
3321*4882a593Smuzhiyun 
3322*4882a593Smuzhiyun 	/* security context too */
3323*4882a593Smuzhiyun 	if (len >= (pol->sadb_x_policy_len*8 +
3324*4882a593Smuzhiyun 	    sizeof(struct sadb_x_sec_ctx))) {
3325*4882a593Smuzhiyun 		char *p = (char *)pol;
3326*4882a593Smuzhiyun 		struct xfrm_user_sec_ctx *uctx;
3327*4882a593Smuzhiyun 
3328*4882a593Smuzhiyun 		p += pol->sadb_x_policy_len*8;
3329*4882a593Smuzhiyun 		sec_ctx = (struct sadb_x_sec_ctx *)p;
3330*4882a593Smuzhiyun 		if (len < pol->sadb_x_policy_len*8 +
3331*4882a593Smuzhiyun 		    sec_ctx->sadb_x_sec_len*8) {
3332*4882a593Smuzhiyun 			*dir = -EINVAL;
3333*4882a593Smuzhiyun 			goto out;
3334*4882a593Smuzhiyun 		}
3335*4882a593Smuzhiyun 		if ((*dir = verify_sec_ctx_len(p)))
3336*4882a593Smuzhiyun 			goto out;
3337*4882a593Smuzhiyun 		uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx, GFP_ATOMIC);
3338*4882a593Smuzhiyun 		*dir = security_xfrm_policy_alloc(&xp->security, uctx, GFP_ATOMIC);
3339*4882a593Smuzhiyun 		kfree(uctx);
3340*4882a593Smuzhiyun 
3341*4882a593Smuzhiyun 		if (*dir)
3342*4882a593Smuzhiyun 			goto out;
3343*4882a593Smuzhiyun 	}
3344*4882a593Smuzhiyun 
3345*4882a593Smuzhiyun 	*dir = pol->sadb_x_policy_dir-1;
3346*4882a593Smuzhiyun 	return xp;
3347*4882a593Smuzhiyun 
3348*4882a593Smuzhiyun out:
3349*4882a593Smuzhiyun 	xp->walk.dead = 1;
3350*4882a593Smuzhiyun 	xfrm_policy_destroy(xp);
3351*4882a593Smuzhiyun 	return NULL;
3352*4882a593Smuzhiyun }
3353*4882a593Smuzhiyun 
pfkey_send_new_mapping(struct xfrm_state * x,xfrm_address_t * ipaddr,__be16 sport)3354*4882a593Smuzhiyun static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport)
3355*4882a593Smuzhiyun {
3356*4882a593Smuzhiyun 	struct sk_buff *skb;
3357*4882a593Smuzhiyun 	struct sadb_msg *hdr;
3358*4882a593Smuzhiyun 	struct sadb_sa *sa;
3359*4882a593Smuzhiyun 	struct sadb_address *addr;
3360*4882a593Smuzhiyun 	struct sadb_x_nat_t_port *n_port;
3361*4882a593Smuzhiyun 	int sockaddr_size;
3362*4882a593Smuzhiyun 	int size;
3363*4882a593Smuzhiyun 	__u8 satype = (x->id.proto == IPPROTO_ESP ? SADB_SATYPE_ESP : 0);
3364*4882a593Smuzhiyun 	struct xfrm_encap_tmpl *natt = NULL;
3365*4882a593Smuzhiyun 
3366*4882a593Smuzhiyun 	sockaddr_size = pfkey_sockaddr_size(x->props.family);
3367*4882a593Smuzhiyun 	if (!sockaddr_size)
3368*4882a593Smuzhiyun 		return -EINVAL;
3369*4882a593Smuzhiyun 
3370*4882a593Smuzhiyun 	if (!satype)
3371*4882a593Smuzhiyun 		return -EINVAL;
3372*4882a593Smuzhiyun 
3373*4882a593Smuzhiyun 	if (!x->encap)
3374*4882a593Smuzhiyun 		return -EINVAL;
3375*4882a593Smuzhiyun 
3376*4882a593Smuzhiyun 	natt = x->encap;
3377*4882a593Smuzhiyun 
3378*4882a593Smuzhiyun 	/* Build an SADB_X_NAT_T_NEW_MAPPING message:
3379*4882a593Smuzhiyun 	 *
3380*4882a593Smuzhiyun 	 * HDR | SA | ADDRESS_SRC (old addr) | NAT_T_SPORT (old port) |
3381*4882a593Smuzhiyun 	 * ADDRESS_DST (new addr) | NAT_T_DPORT (new port)
3382*4882a593Smuzhiyun 	 */
3383*4882a593Smuzhiyun 
3384*4882a593Smuzhiyun 	size = sizeof(struct sadb_msg) +
3385*4882a593Smuzhiyun 		sizeof(struct sadb_sa) +
3386*4882a593Smuzhiyun 		(sizeof(struct sadb_address) * 2) +
3387*4882a593Smuzhiyun 		(sockaddr_size * 2) +
3388*4882a593Smuzhiyun 		(sizeof(struct sadb_x_nat_t_port) * 2);
3389*4882a593Smuzhiyun 
3390*4882a593Smuzhiyun 	skb =  alloc_skb(size + 16, GFP_ATOMIC);
3391*4882a593Smuzhiyun 	if (skb == NULL)
3392*4882a593Smuzhiyun 		return -ENOMEM;
3393*4882a593Smuzhiyun 
3394*4882a593Smuzhiyun 	hdr = skb_put(skb, sizeof(struct sadb_msg));
3395*4882a593Smuzhiyun 	hdr->sadb_msg_version = PF_KEY_V2;
3396*4882a593Smuzhiyun 	hdr->sadb_msg_type = SADB_X_NAT_T_NEW_MAPPING;
3397*4882a593Smuzhiyun 	hdr->sadb_msg_satype = satype;
3398*4882a593Smuzhiyun 	hdr->sadb_msg_len = size / sizeof(uint64_t);
3399*4882a593Smuzhiyun 	hdr->sadb_msg_errno = 0;
3400*4882a593Smuzhiyun 	hdr->sadb_msg_reserved = 0;
3401*4882a593Smuzhiyun 	hdr->sadb_msg_seq = x->km.seq = get_acqseq();
3402*4882a593Smuzhiyun 	hdr->sadb_msg_pid = 0;
3403*4882a593Smuzhiyun 
3404*4882a593Smuzhiyun 	/* SA */
3405*4882a593Smuzhiyun 	sa = skb_put(skb, sizeof(struct sadb_sa));
3406*4882a593Smuzhiyun 	sa->sadb_sa_len = sizeof(struct sadb_sa)/sizeof(uint64_t);
3407*4882a593Smuzhiyun 	sa->sadb_sa_exttype = SADB_EXT_SA;
3408*4882a593Smuzhiyun 	sa->sadb_sa_spi = x->id.spi;
3409*4882a593Smuzhiyun 	sa->sadb_sa_replay = 0;
3410*4882a593Smuzhiyun 	sa->sadb_sa_state = 0;
3411*4882a593Smuzhiyun 	sa->sadb_sa_auth = 0;
3412*4882a593Smuzhiyun 	sa->sadb_sa_encrypt = 0;
3413*4882a593Smuzhiyun 	sa->sadb_sa_flags = 0;
3414*4882a593Smuzhiyun 
3415*4882a593Smuzhiyun 	/* ADDRESS_SRC (old addr) */
3416*4882a593Smuzhiyun 	addr = skb_put(skb, sizeof(struct sadb_address) + sockaddr_size);
3417*4882a593Smuzhiyun 	addr->sadb_address_len =
3418*4882a593Smuzhiyun 		(sizeof(struct sadb_address)+sockaddr_size)/
3419*4882a593Smuzhiyun 			sizeof(uint64_t);
3420*4882a593Smuzhiyun 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
3421*4882a593Smuzhiyun 	addr->sadb_address_proto = 0;
3422*4882a593Smuzhiyun 	addr->sadb_address_reserved = 0;
3423*4882a593Smuzhiyun 	addr->sadb_address_prefixlen =
3424*4882a593Smuzhiyun 		pfkey_sockaddr_fill(&x->props.saddr, 0,
3425*4882a593Smuzhiyun 				    (struct sockaddr *) (addr + 1),
3426*4882a593Smuzhiyun 				    x->props.family);
3427*4882a593Smuzhiyun 	if (!addr->sadb_address_prefixlen)
3428*4882a593Smuzhiyun 		BUG();
3429*4882a593Smuzhiyun 
3430*4882a593Smuzhiyun 	/* NAT_T_SPORT (old port) */
3431*4882a593Smuzhiyun 	n_port = skb_put(skb, sizeof(*n_port));
3432*4882a593Smuzhiyun 	n_port->sadb_x_nat_t_port_len = sizeof(*n_port)/sizeof(uint64_t);
3433*4882a593Smuzhiyun 	n_port->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_SPORT;
3434*4882a593Smuzhiyun 	n_port->sadb_x_nat_t_port_port = natt->encap_sport;
3435*4882a593Smuzhiyun 	n_port->sadb_x_nat_t_port_reserved = 0;
3436*4882a593Smuzhiyun 
3437*4882a593Smuzhiyun 	/* ADDRESS_DST (new addr) */
3438*4882a593Smuzhiyun 	addr = skb_put(skb, sizeof(struct sadb_address) + sockaddr_size);
3439*4882a593Smuzhiyun 	addr->sadb_address_len =
3440*4882a593Smuzhiyun 		(sizeof(struct sadb_address)+sockaddr_size)/
3441*4882a593Smuzhiyun 			sizeof(uint64_t);
3442*4882a593Smuzhiyun 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
3443*4882a593Smuzhiyun 	addr->sadb_address_proto = 0;
3444*4882a593Smuzhiyun 	addr->sadb_address_reserved = 0;
3445*4882a593Smuzhiyun 	addr->sadb_address_prefixlen =
3446*4882a593Smuzhiyun 		pfkey_sockaddr_fill(ipaddr, 0,
3447*4882a593Smuzhiyun 				    (struct sockaddr *) (addr + 1),
3448*4882a593Smuzhiyun 				    x->props.family);
3449*4882a593Smuzhiyun 	if (!addr->sadb_address_prefixlen)
3450*4882a593Smuzhiyun 		BUG();
3451*4882a593Smuzhiyun 
3452*4882a593Smuzhiyun 	/* NAT_T_DPORT (new port) */
3453*4882a593Smuzhiyun 	n_port = skb_put(skb, sizeof(*n_port));
3454*4882a593Smuzhiyun 	n_port->sadb_x_nat_t_port_len = sizeof(*n_port)/sizeof(uint64_t);
3455*4882a593Smuzhiyun 	n_port->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_DPORT;
3456*4882a593Smuzhiyun 	n_port->sadb_x_nat_t_port_port = sport;
3457*4882a593Smuzhiyun 	n_port->sadb_x_nat_t_port_reserved = 0;
3458*4882a593Smuzhiyun 
3459*4882a593Smuzhiyun 	return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL,
3460*4882a593Smuzhiyun 			       xs_net(x));
3461*4882a593Smuzhiyun }
3462*4882a593Smuzhiyun 
3463*4882a593Smuzhiyun #ifdef CONFIG_NET_KEY_MIGRATE
set_sadb_address(struct sk_buff * skb,int sasize,int type,const struct xfrm_selector * sel)3464*4882a593Smuzhiyun static int set_sadb_address(struct sk_buff *skb, int sasize, int type,
3465*4882a593Smuzhiyun 			    const struct xfrm_selector *sel)
3466*4882a593Smuzhiyun {
3467*4882a593Smuzhiyun 	struct sadb_address *addr;
3468*4882a593Smuzhiyun 	addr = skb_put(skb, sizeof(struct sadb_address) + sasize);
3469*4882a593Smuzhiyun 	addr->sadb_address_len = (sizeof(struct sadb_address) + sasize)/8;
3470*4882a593Smuzhiyun 	addr->sadb_address_exttype = type;
3471*4882a593Smuzhiyun 	addr->sadb_address_proto = sel->proto;
3472*4882a593Smuzhiyun 	addr->sadb_address_reserved = 0;
3473*4882a593Smuzhiyun 
3474*4882a593Smuzhiyun 	switch (type) {
3475*4882a593Smuzhiyun 	case SADB_EXT_ADDRESS_SRC:
3476*4882a593Smuzhiyun 		addr->sadb_address_prefixlen = sel->prefixlen_s;
3477*4882a593Smuzhiyun 		pfkey_sockaddr_fill(&sel->saddr, 0,
3478*4882a593Smuzhiyun 				    (struct sockaddr *)(addr + 1),
3479*4882a593Smuzhiyun 				    sel->family);
3480*4882a593Smuzhiyun 		break;
3481*4882a593Smuzhiyun 	case SADB_EXT_ADDRESS_DST:
3482*4882a593Smuzhiyun 		addr->sadb_address_prefixlen = sel->prefixlen_d;
3483*4882a593Smuzhiyun 		pfkey_sockaddr_fill(&sel->daddr, 0,
3484*4882a593Smuzhiyun 				    (struct sockaddr *)(addr + 1),
3485*4882a593Smuzhiyun 				    sel->family);
3486*4882a593Smuzhiyun 		break;
3487*4882a593Smuzhiyun 	default:
3488*4882a593Smuzhiyun 		return -EINVAL;
3489*4882a593Smuzhiyun 	}
3490*4882a593Smuzhiyun 
3491*4882a593Smuzhiyun 	return 0;
3492*4882a593Smuzhiyun }
3493*4882a593Smuzhiyun 
3494*4882a593Smuzhiyun 
set_sadb_kmaddress(struct sk_buff * skb,const struct xfrm_kmaddress * k)3495*4882a593Smuzhiyun static int set_sadb_kmaddress(struct sk_buff *skb, const struct xfrm_kmaddress *k)
3496*4882a593Smuzhiyun {
3497*4882a593Smuzhiyun 	struct sadb_x_kmaddress *kma;
3498*4882a593Smuzhiyun 	u8 *sa;
3499*4882a593Smuzhiyun 	int family = k->family;
3500*4882a593Smuzhiyun 	int socklen = pfkey_sockaddr_len(family);
3501*4882a593Smuzhiyun 	int size_req;
3502*4882a593Smuzhiyun 
3503*4882a593Smuzhiyun 	size_req = (sizeof(struct sadb_x_kmaddress) +
3504*4882a593Smuzhiyun 		    pfkey_sockaddr_pair_size(family));
3505*4882a593Smuzhiyun 
3506*4882a593Smuzhiyun 	kma = skb_put_zero(skb, size_req);
3507*4882a593Smuzhiyun 	kma->sadb_x_kmaddress_len = size_req / 8;
3508*4882a593Smuzhiyun 	kma->sadb_x_kmaddress_exttype = SADB_X_EXT_KMADDRESS;
3509*4882a593Smuzhiyun 	kma->sadb_x_kmaddress_reserved = k->reserved;
3510*4882a593Smuzhiyun 
3511*4882a593Smuzhiyun 	sa = (u8 *)(kma + 1);
3512*4882a593Smuzhiyun 	if (!pfkey_sockaddr_fill(&k->local, 0, (struct sockaddr *)sa, family) ||
3513*4882a593Smuzhiyun 	    !pfkey_sockaddr_fill(&k->remote, 0, (struct sockaddr *)(sa+socklen), family))
3514*4882a593Smuzhiyun 		return -EINVAL;
3515*4882a593Smuzhiyun 
3516*4882a593Smuzhiyun 	return 0;
3517*4882a593Smuzhiyun }
3518*4882a593Smuzhiyun 
set_ipsecrequest(struct sk_buff * skb,uint8_t proto,uint8_t mode,int level,uint32_t reqid,uint8_t family,const xfrm_address_t * src,const xfrm_address_t * dst)3519*4882a593Smuzhiyun static int set_ipsecrequest(struct sk_buff *skb,
3520*4882a593Smuzhiyun 			    uint8_t proto, uint8_t mode, int level,
3521*4882a593Smuzhiyun 			    uint32_t reqid, uint8_t family,
3522*4882a593Smuzhiyun 			    const xfrm_address_t *src, const xfrm_address_t *dst)
3523*4882a593Smuzhiyun {
3524*4882a593Smuzhiyun 	struct sadb_x_ipsecrequest *rq;
3525*4882a593Smuzhiyun 	u8 *sa;
3526*4882a593Smuzhiyun 	int socklen = pfkey_sockaddr_len(family);
3527*4882a593Smuzhiyun 	int size_req;
3528*4882a593Smuzhiyun 
3529*4882a593Smuzhiyun 	size_req = sizeof(struct sadb_x_ipsecrequest) +
3530*4882a593Smuzhiyun 		   pfkey_sockaddr_pair_size(family);
3531*4882a593Smuzhiyun 
3532*4882a593Smuzhiyun 	rq = skb_put_zero(skb, size_req);
3533*4882a593Smuzhiyun 	rq->sadb_x_ipsecrequest_len = size_req;
3534*4882a593Smuzhiyun 	rq->sadb_x_ipsecrequest_proto = proto;
3535*4882a593Smuzhiyun 	rq->sadb_x_ipsecrequest_mode = mode;
3536*4882a593Smuzhiyun 	rq->sadb_x_ipsecrequest_level = level;
3537*4882a593Smuzhiyun 	rq->sadb_x_ipsecrequest_reqid = reqid;
3538*4882a593Smuzhiyun 
3539*4882a593Smuzhiyun 	sa = (u8 *) (rq + 1);
3540*4882a593Smuzhiyun 	if (!pfkey_sockaddr_fill(src, 0, (struct sockaddr *)sa, family) ||
3541*4882a593Smuzhiyun 	    !pfkey_sockaddr_fill(dst, 0, (struct sockaddr *)(sa + socklen), family))
3542*4882a593Smuzhiyun 		return -EINVAL;
3543*4882a593Smuzhiyun 
3544*4882a593Smuzhiyun 	return 0;
3545*4882a593Smuzhiyun }
3546*4882a593Smuzhiyun #endif
3547*4882a593Smuzhiyun 
3548*4882a593Smuzhiyun #ifdef CONFIG_NET_KEY_MIGRATE
pfkey_send_migrate(const struct xfrm_selector * sel,u8 dir,u8 type,const struct xfrm_migrate * m,int num_bundles,const struct xfrm_kmaddress * k,const struct xfrm_encap_tmpl * encap)3549*4882a593Smuzhiyun static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
3550*4882a593Smuzhiyun 			      const struct xfrm_migrate *m, int num_bundles,
3551*4882a593Smuzhiyun 			      const struct xfrm_kmaddress *k,
3552*4882a593Smuzhiyun 			      const struct xfrm_encap_tmpl *encap)
3553*4882a593Smuzhiyun {
3554*4882a593Smuzhiyun 	int i;
3555*4882a593Smuzhiyun 	int sasize_sel;
3556*4882a593Smuzhiyun 	int size = 0;
3557*4882a593Smuzhiyun 	int size_pol = 0;
3558*4882a593Smuzhiyun 	struct sk_buff *skb;
3559*4882a593Smuzhiyun 	struct sadb_msg *hdr;
3560*4882a593Smuzhiyun 	struct sadb_x_policy *pol;
3561*4882a593Smuzhiyun 	const struct xfrm_migrate *mp;
3562*4882a593Smuzhiyun 
3563*4882a593Smuzhiyun 	if (type != XFRM_POLICY_TYPE_MAIN)
3564*4882a593Smuzhiyun 		return 0;
3565*4882a593Smuzhiyun 
3566*4882a593Smuzhiyun 	if (num_bundles <= 0 || num_bundles > XFRM_MAX_DEPTH)
3567*4882a593Smuzhiyun 		return -EINVAL;
3568*4882a593Smuzhiyun 
3569*4882a593Smuzhiyun 	if (k != NULL) {
3570*4882a593Smuzhiyun 		/* addresses for KM */
3571*4882a593Smuzhiyun 		size += PFKEY_ALIGN8(sizeof(struct sadb_x_kmaddress) +
3572*4882a593Smuzhiyun 				     pfkey_sockaddr_pair_size(k->family));
3573*4882a593Smuzhiyun 	}
3574*4882a593Smuzhiyun 
3575*4882a593Smuzhiyun 	/* selector */
3576*4882a593Smuzhiyun 	sasize_sel = pfkey_sockaddr_size(sel->family);
3577*4882a593Smuzhiyun 	if (!sasize_sel)
3578*4882a593Smuzhiyun 		return -EINVAL;
3579*4882a593Smuzhiyun 	size += (sizeof(struct sadb_address) + sasize_sel) * 2;
3580*4882a593Smuzhiyun 
3581*4882a593Smuzhiyun 	/* policy info */
3582*4882a593Smuzhiyun 	size_pol += sizeof(struct sadb_x_policy);
3583*4882a593Smuzhiyun 
3584*4882a593Smuzhiyun 	/* ipsecrequests */
3585*4882a593Smuzhiyun 	for (i = 0, mp = m; i < num_bundles; i++, mp++) {
3586*4882a593Smuzhiyun 		/* old locator pair */
3587*4882a593Smuzhiyun 		size_pol += sizeof(struct sadb_x_ipsecrequest) +
3588*4882a593Smuzhiyun 			    pfkey_sockaddr_pair_size(mp->old_family);
3589*4882a593Smuzhiyun 		/* new locator pair */
3590*4882a593Smuzhiyun 		size_pol += sizeof(struct sadb_x_ipsecrequest) +
3591*4882a593Smuzhiyun 			    pfkey_sockaddr_pair_size(mp->new_family);
3592*4882a593Smuzhiyun 	}
3593*4882a593Smuzhiyun 
3594*4882a593Smuzhiyun 	size += sizeof(struct sadb_msg) + size_pol;
3595*4882a593Smuzhiyun 
3596*4882a593Smuzhiyun 	/* alloc buffer */
3597*4882a593Smuzhiyun 	skb = alloc_skb(size, GFP_ATOMIC);
3598*4882a593Smuzhiyun 	if (skb == NULL)
3599*4882a593Smuzhiyun 		return -ENOMEM;
3600*4882a593Smuzhiyun 
3601*4882a593Smuzhiyun 	hdr = skb_put(skb, sizeof(struct sadb_msg));
3602*4882a593Smuzhiyun 	hdr->sadb_msg_version = PF_KEY_V2;
3603*4882a593Smuzhiyun 	hdr->sadb_msg_type = SADB_X_MIGRATE;
3604*4882a593Smuzhiyun 	hdr->sadb_msg_satype = pfkey_proto2satype(m->proto);
3605*4882a593Smuzhiyun 	hdr->sadb_msg_len = size / 8;
3606*4882a593Smuzhiyun 	hdr->sadb_msg_errno = 0;
3607*4882a593Smuzhiyun 	hdr->sadb_msg_reserved = 0;
3608*4882a593Smuzhiyun 	hdr->sadb_msg_seq = 0;
3609*4882a593Smuzhiyun 	hdr->sadb_msg_pid = 0;
3610*4882a593Smuzhiyun 
3611*4882a593Smuzhiyun 	/* Addresses to be used by KM for negotiation, if ext is available */
3612*4882a593Smuzhiyun 	if (k != NULL && (set_sadb_kmaddress(skb, k) < 0))
3613*4882a593Smuzhiyun 		goto err;
3614*4882a593Smuzhiyun 
3615*4882a593Smuzhiyun 	/* selector src */
3616*4882a593Smuzhiyun 	set_sadb_address(skb, sasize_sel, SADB_EXT_ADDRESS_SRC, sel);
3617*4882a593Smuzhiyun 
3618*4882a593Smuzhiyun 	/* selector dst */
3619*4882a593Smuzhiyun 	set_sadb_address(skb, sasize_sel, SADB_EXT_ADDRESS_DST, sel);
3620*4882a593Smuzhiyun 
3621*4882a593Smuzhiyun 	/* policy information */
3622*4882a593Smuzhiyun 	pol = skb_put(skb, sizeof(struct sadb_x_policy));
3623*4882a593Smuzhiyun 	pol->sadb_x_policy_len = size_pol / 8;
3624*4882a593Smuzhiyun 	pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
3625*4882a593Smuzhiyun 	pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
3626*4882a593Smuzhiyun 	pol->sadb_x_policy_dir = dir + 1;
3627*4882a593Smuzhiyun 	pol->sadb_x_policy_reserved = 0;
3628*4882a593Smuzhiyun 	pol->sadb_x_policy_id = 0;
3629*4882a593Smuzhiyun 	pol->sadb_x_policy_priority = 0;
3630*4882a593Smuzhiyun 
3631*4882a593Smuzhiyun 	for (i = 0, mp = m; i < num_bundles; i++, mp++) {
3632*4882a593Smuzhiyun 		/* old ipsecrequest */
3633*4882a593Smuzhiyun 		int mode = pfkey_mode_from_xfrm(mp->mode);
3634*4882a593Smuzhiyun 		if (mode < 0)
3635*4882a593Smuzhiyun 			goto err;
3636*4882a593Smuzhiyun 		if (set_ipsecrequest(skb, mp->proto, mode,
3637*4882a593Smuzhiyun 				     (mp->reqid ?  IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_REQUIRE),
3638*4882a593Smuzhiyun 				     mp->reqid, mp->old_family,
3639*4882a593Smuzhiyun 				     &mp->old_saddr, &mp->old_daddr) < 0)
3640*4882a593Smuzhiyun 			goto err;
3641*4882a593Smuzhiyun 
3642*4882a593Smuzhiyun 		/* new ipsecrequest */
3643*4882a593Smuzhiyun 		if (set_ipsecrequest(skb, mp->proto, mode,
3644*4882a593Smuzhiyun 				     (mp->reqid ? IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_REQUIRE),
3645*4882a593Smuzhiyun 				     mp->reqid, mp->new_family,
3646*4882a593Smuzhiyun 				     &mp->new_saddr, &mp->new_daddr) < 0)
3647*4882a593Smuzhiyun 			goto err;
3648*4882a593Smuzhiyun 	}
3649*4882a593Smuzhiyun 
3650*4882a593Smuzhiyun 	/* broadcast migrate message to sockets */
3651*4882a593Smuzhiyun 	pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, &init_net);
3652*4882a593Smuzhiyun 
3653*4882a593Smuzhiyun 	return 0;
3654*4882a593Smuzhiyun 
3655*4882a593Smuzhiyun err:
3656*4882a593Smuzhiyun 	kfree_skb(skb);
3657*4882a593Smuzhiyun 	return -EINVAL;
3658*4882a593Smuzhiyun }
3659*4882a593Smuzhiyun #else
pfkey_send_migrate(const struct xfrm_selector * sel,u8 dir,u8 type,const struct xfrm_migrate * m,int num_bundles,const struct xfrm_kmaddress * k,const struct xfrm_encap_tmpl * encap)3660*4882a593Smuzhiyun static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
3661*4882a593Smuzhiyun 			      const struct xfrm_migrate *m, int num_bundles,
3662*4882a593Smuzhiyun 			      const struct xfrm_kmaddress *k,
3663*4882a593Smuzhiyun 			      const struct xfrm_encap_tmpl *encap)
3664*4882a593Smuzhiyun {
3665*4882a593Smuzhiyun 	return -ENOPROTOOPT;
3666*4882a593Smuzhiyun }
3667*4882a593Smuzhiyun #endif
3668*4882a593Smuzhiyun 
pfkey_sendmsg(struct socket * sock,struct msghdr * msg,size_t len)3669*4882a593Smuzhiyun static int pfkey_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
3670*4882a593Smuzhiyun {
3671*4882a593Smuzhiyun 	struct sock *sk = sock->sk;
3672*4882a593Smuzhiyun 	struct sk_buff *skb = NULL;
3673*4882a593Smuzhiyun 	struct sadb_msg *hdr = NULL;
3674*4882a593Smuzhiyun 	int err;
3675*4882a593Smuzhiyun 	struct net *net = sock_net(sk);
3676*4882a593Smuzhiyun 
3677*4882a593Smuzhiyun 	err = -EOPNOTSUPP;
3678*4882a593Smuzhiyun 	if (msg->msg_flags & MSG_OOB)
3679*4882a593Smuzhiyun 		goto out;
3680*4882a593Smuzhiyun 
3681*4882a593Smuzhiyun 	err = -EMSGSIZE;
3682*4882a593Smuzhiyun 	if ((unsigned int)len > sk->sk_sndbuf - 32)
3683*4882a593Smuzhiyun 		goto out;
3684*4882a593Smuzhiyun 
3685*4882a593Smuzhiyun 	err = -ENOBUFS;
3686*4882a593Smuzhiyun 	skb = alloc_skb(len, GFP_KERNEL);
3687*4882a593Smuzhiyun 	if (skb == NULL)
3688*4882a593Smuzhiyun 		goto out;
3689*4882a593Smuzhiyun 
3690*4882a593Smuzhiyun 	err = -EFAULT;
3691*4882a593Smuzhiyun 	if (memcpy_from_msg(skb_put(skb,len), msg, len))
3692*4882a593Smuzhiyun 		goto out;
3693*4882a593Smuzhiyun 
3694*4882a593Smuzhiyun 	hdr = pfkey_get_base_msg(skb, &err);
3695*4882a593Smuzhiyun 	if (!hdr)
3696*4882a593Smuzhiyun 		goto out;
3697*4882a593Smuzhiyun 
3698*4882a593Smuzhiyun 	mutex_lock(&net->xfrm.xfrm_cfg_mutex);
3699*4882a593Smuzhiyun 	err = pfkey_process(sk, skb, hdr);
3700*4882a593Smuzhiyun 	mutex_unlock(&net->xfrm.xfrm_cfg_mutex);
3701*4882a593Smuzhiyun 
3702*4882a593Smuzhiyun out:
3703*4882a593Smuzhiyun 	if (err && hdr && pfkey_error(hdr, err, sk) == 0)
3704*4882a593Smuzhiyun 		err = 0;
3705*4882a593Smuzhiyun 	kfree_skb(skb);
3706*4882a593Smuzhiyun 
3707*4882a593Smuzhiyun 	return err ? : len;
3708*4882a593Smuzhiyun }
3709*4882a593Smuzhiyun 
pfkey_recvmsg(struct socket * sock,struct msghdr * msg,size_t len,int flags)3710*4882a593Smuzhiyun static int pfkey_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
3711*4882a593Smuzhiyun 			 int flags)
3712*4882a593Smuzhiyun {
3713*4882a593Smuzhiyun 	struct sock *sk = sock->sk;
3714*4882a593Smuzhiyun 	struct pfkey_sock *pfk = pfkey_sk(sk);
3715*4882a593Smuzhiyun 	struct sk_buff *skb;
3716*4882a593Smuzhiyun 	int copied, err;
3717*4882a593Smuzhiyun 
3718*4882a593Smuzhiyun 	err = -EINVAL;
3719*4882a593Smuzhiyun 	if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT))
3720*4882a593Smuzhiyun 		goto out;
3721*4882a593Smuzhiyun 
3722*4882a593Smuzhiyun 	skb = skb_recv_datagram(sk, flags, flags & MSG_DONTWAIT, &err);
3723*4882a593Smuzhiyun 	if (skb == NULL)
3724*4882a593Smuzhiyun 		goto out;
3725*4882a593Smuzhiyun 
3726*4882a593Smuzhiyun 	copied = skb->len;
3727*4882a593Smuzhiyun 	if (copied > len) {
3728*4882a593Smuzhiyun 		msg->msg_flags |= MSG_TRUNC;
3729*4882a593Smuzhiyun 		copied = len;
3730*4882a593Smuzhiyun 	}
3731*4882a593Smuzhiyun 
3732*4882a593Smuzhiyun 	skb_reset_transport_header(skb);
3733*4882a593Smuzhiyun 	err = skb_copy_datagram_msg(skb, 0, msg, copied);
3734*4882a593Smuzhiyun 	if (err)
3735*4882a593Smuzhiyun 		goto out_free;
3736*4882a593Smuzhiyun 
3737*4882a593Smuzhiyun 	sock_recv_ts_and_drops(msg, sk, skb);
3738*4882a593Smuzhiyun 
3739*4882a593Smuzhiyun 	err = (flags & MSG_TRUNC) ? skb->len : copied;
3740*4882a593Smuzhiyun 
3741*4882a593Smuzhiyun 	if (pfk->dump.dump != NULL &&
3742*4882a593Smuzhiyun 	    3 * atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf)
3743*4882a593Smuzhiyun 		pfkey_do_dump(pfk);
3744*4882a593Smuzhiyun 
3745*4882a593Smuzhiyun out_free:
3746*4882a593Smuzhiyun 	skb_free_datagram(sk, skb);
3747*4882a593Smuzhiyun out:
3748*4882a593Smuzhiyun 	return err;
3749*4882a593Smuzhiyun }
3750*4882a593Smuzhiyun 
3751*4882a593Smuzhiyun static const struct proto_ops pfkey_ops = {
3752*4882a593Smuzhiyun 	.family		=	PF_KEY,
3753*4882a593Smuzhiyun 	.owner		=	THIS_MODULE,
3754*4882a593Smuzhiyun 	/* Operations that make no sense on pfkey sockets. */
3755*4882a593Smuzhiyun 	.bind		=	sock_no_bind,
3756*4882a593Smuzhiyun 	.connect	=	sock_no_connect,
3757*4882a593Smuzhiyun 	.socketpair	=	sock_no_socketpair,
3758*4882a593Smuzhiyun 	.accept		=	sock_no_accept,
3759*4882a593Smuzhiyun 	.getname	=	sock_no_getname,
3760*4882a593Smuzhiyun 	.ioctl		=	sock_no_ioctl,
3761*4882a593Smuzhiyun 	.listen		=	sock_no_listen,
3762*4882a593Smuzhiyun 	.shutdown	=	sock_no_shutdown,
3763*4882a593Smuzhiyun 	.mmap		=	sock_no_mmap,
3764*4882a593Smuzhiyun 	.sendpage	=	sock_no_sendpage,
3765*4882a593Smuzhiyun 
3766*4882a593Smuzhiyun 	/* Now the operations that really occur. */
3767*4882a593Smuzhiyun 	.release	=	pfkey_release,
3768*4882a593Smuzhiyun 	.poll		=	datagram_poll,
3769*4882a593Smuzhiyun 	.sendmsg	=	pfkey_sendmsg,
3770*4882a593Smuzhiyun 	.recvmsg	=	pfkey_recvmsg,
3771*4882a593Smuzhiyun };
3772*4882a593Smuzhiyun 
3773*4882a593Smuzhiyun static const struct net_proto_family pfkey_family_ops = {
3774*4882a593Smuzhiyun 	.family	=	PF_KEY,
3775*4882a593Smuzhiyun 	.create	=	pfkey_create,
3776*4882a593Smuzhiyun 	.owner	=	THIS_MODULE,
3777*4882a593Smuzhiyun };
3778*4882a593Smuzhiyun 
3779*4882a593Smuzhiyun #ifdef CONFIG_PROC_FS
pfkey_seq_show(struct seq_file * f,void * v)3780*4882a593Smuzhiyun static int pfkey_seq_show(struct seq_file *f, void *v)
3781*4882a593Smuzhiyun {
3782*4882a593Smuzhiyun 	struct sock *s = sk_entry(v);
3783*4882a593Smuzhiyun 
3784*4882a593Smuzhiyun 	if (v == SEQ_START_TOKEN)
3785*4882a593Smuzhiyun 		seq_printf(f ,"sk       RefCnt Rmem   Wmem   User   Inode\n");
3786*4882a593Smuzhiyun 	else
3787*4882a593Smuzhiyun 		seq_printf(f, "%pK %-6d %-6u %-6u %-6u %-6lu\n",
3788*4882a593Smuzhiyun 			       s,
3789*4882a593Smuzhiyun 			       refcount_read(&s->sk_refcnt),
3790*4882a593Smuzhiyun 			       sk_rmem_alloc_get(s),
3791*4882a593Smuzhiyun 			       sk_wmem_alloc_get(s),
3792*4882a593Smuzhiyun 			       from_kuid_munged(seq_user_ns(f), sock_i_uid(s)),
3793*4882a593Smuzhiyun 			       sock_i_ino(s)
3794*4882a593Smuzhiyun 			       );
3795*4882a593Smuzhiyun 	return 0;
3796*4882a593Smuzhiyun }
3797*4882a593Smuzhiyun 
pfkey_seq_start(struct seq_file * f,loff_t * ppos)3798*4882a593Smuzhiyun static void *pfkey_seq_start(struct seq_file *f, loff_t *ppos)
3799*4882a593Smuzhiyun 	__acquires(rcu)
3800*4882a593Smuzhiyun {
3801*4882a593Smuzhiyun 	struct net *net = seq_file_net(f);
3802*4882a593Smuzhiyun 	struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
3803*4882a593Smuzhiyun 
3804*4882a593Smuzhiyun 	rcu_read_lock();
3805*4882a593Smuzhiyun 	return seq_hlist_start_head_rcu(&net_pfkey->table, *ppos);
3806*4882a593Smuzhiyun }
3807*4882a593Smuzhiyun 
pfkey_seq_next(struct seq_file * f,void * v,loff_t * ppos)3808*4882a593Smuzhiyun static void *pfkey_seq_next(struct seq_file *f, void *v, loff_t *ppos)
3809*4882a593Smuzhiyun {
3810*4882a593Smuzhiyun 	struct net *net = seq_file_net(f);
3811*4882a593Smuzhiyun 	struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
3812*4882a593Smuzhiyun 
3813*4882a593Smuzhiyun 	return seq_hlist_next_rcu(v, &net_pfkey->table, ppos);
3814*4882a593Smuzhiyun }
3815*4882a593Smuzhiyun 
pfkey_seq_stop(struct seq_file * f,void * v)3816*4882a593Smuzhiyun static void pfkey_seq_stop(struct seq_file *f, void *v)
3817*4882a593Smuzhiyun 	__releases(rcu)
3818*4882a593Smuzhiyun {
3819*4882a593Smuzhiyun 	rcu_read_unlock();
3820*4882a593Smuzhiyun }
3821*4882a593Smuzhiyun 
3822*4882a593Smuzhiyun static const struct seq_operations pfkey_seq_ops = {
3823*4882a593Smuzhiyun 	.start	= pfkey_seq_start,
3824*4882a593Smuzhiyun 	.next	= pfkey_seq_next,
3825*4882a593Smuzhiyun 	.stop	= pfkey_seq_stop,
3826*4882a593Smuzhiyun 	.show	= pfkey_seq_show,
3827*4882a593Smuzhiyun };
3828*4882a593Smuzhiyun 
pfkey_init_proc(struct net * net)3829*4882a593Smuzhiyun static int __net_init pfkey_init_proc(struct net *net)
3830*4882a593Smuzhiyun {
3831*4882a593Smuzhiyun 	struct proc_dir_entry *e;
3832*4882a593Smuzhiyun 
3833*4882a593Smuzhiyun 	e = proc_create_net("pfkey", 0, net->proc_net, &pfkey_seq_ops,
3834*4882a593Smuzhiyun 			sizeof(struct seq_net_private));
3835*4882a593Smuzhiyun 	if (e == NULL)
3836*4882a593Smuzhiyun 		return -ENOMEM;
3837*4882a593Smuzhiyun 
3838*4882a593Smuzhiyun 	return 0;
3839*4882a593Smuzhiyun }
3840*4882a593Smuzhiyun 
pfkey_exit_proc(struct net * net)3841*4882a593Smuzhiyun static void __net_exit pfkey_exit_proc(struct net *net)
3842*4882a593Smuzhiyun {
3843*4882a593Smuzhiyun 	remove_proc_entry("pfkey", net->proc_net);
3844*4882a593Smuzhiyun }
3845*4882a593Smuzhiyun #else
pfkey_init_proc(struct net * net)3846*4882a593Smuzhiyun static inline int pfkey_init_proc(struct net *net)
3847*4882a593Smuzhiyun {
3848*4882a593Smuzhiyun 	return 0;
3849*4882a593Smuzhiyun }
3850*4882a593Smuzhiyun 
pfkey_exit_proc(struct net * net)3851*4882a593Smuzhiyun static inline void pfkey_exit_proc(struct net *net)
3852*4882a593Smuzhiyun {
3853*4882a593Smuzhiyun }
3854*4882a593Smuzhiyun #endif
3855*4882a593Smuzhiyun 
3856*4882a593Smuzhiyun static struct xfrm_mgr pfkeyv2_mgr =
3857*4882a593Smuzhiyun {
3858*4882a593Smuzhiyun 	.notify		= pfkey_send_notify,
3859*4882a593Smuzhiyun 	.acquire	= pfkey_send_acquire,
3860*4882a593Smuzhiyun 	.compile_policy	= pfkey_compile_policy,
3861*4882a593Smuzhiyun 	.new_mapping	= pfkey_send_new_mapping,
3862*4882a593Smuzhiyun 	.notify_policy	= pfkey_send_policy_notify,
3863*4882a593Smuzhiyun 	.migrate	= pfkey_send_migrate,
3864*4882a593Smuzhiyun 	.is_alive	= pfkey_is_alive,
3865*4882a593Smuzhiyun };
3866*4882a593Smuzhiyun 
pfkey_net_init(struct net * net)3867*4882a593Smuzhiyun static int __net_init pfkey_net_init(struct net *net)
3868*4882a593Smuzhiyun {
3869*4882a593Smuzhiyun 	struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
3870*4882a593Smuzhiyun 	int rv;
3871*4882a593Smuzhiyun 
3872*4882a593Smuzhiyun 	INIT_HLIST_HEAD(&net_pfkey->table);
3873*4882a593Smuzhiyun 	atomic_set(&net_pfkey->socks_nr, 0);
3874*4882a593Smuzhiyun 
3875*4882a593Smuzhiyun 	rv = pfkey_init_proc(net);
3876*4882a593Smuzhiyun 
3877*4882a593Smuzhiyun 	return rv;
3878*4882a593Smuzhiyun }
3879*4882a593Smuzhiyun 
pfkey_net_exit(struct net * net)3880*4882a593Smuzhiyun static void __net_exit pfkey_net_exit(struct net *net)
3881*4882a593Smuzhiyun {
3882*4882a593Smuzhiyun 	struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
3883*4882a593Smuzhiyun 
3884*4882a593Smuzhiyun 	pfkey_exit_proc(net);
3885*4882a593Smuzhiyun 	WARN_ON(!hlist_empty(&net_pfkey->table));
3886*4882a593Smuzhiyun }
3887*4882a593Smuzhiyun 
3888*4882a593Smuzhiyun static struct pernet_operations pfkey_net_ops = {
3889*4882a593Smuzhiyun 	.init = pfkey_net_init,
3890*4882a593Smuzhiyun 	.exit = pfkey_net_exit,
3891*4882a593Smuzhiyun 	.id   = &pfkey_net_id,
3892*4882a593Smuzhiyun 	.size = sizeof(struct netns_pfkey),
3893*4882a593Smuzhiyun };
3894*4882a593Smuzhiyun 
ipsec_pfkey_exit(void)3895*4882a593Smuzhiyun static void __exit ipsec_pfkey_exit(void)
3896*4882a593Smuzhiyun {
3897*4882a593Smuzhiyun 	xfrm_unregister_km(&pfkeyv2_mgr);
3898*4882a593Smuzhiyun 	sock_unregister(PF_KEY);
3899*4882a593Smuzhiyun 	unregister_pernet_subsys(&pfkey_net_ops);
3900*4882a593Smuzhiyun 	proto_unregister(&key_proto);
3901*4882a593Smuzhiyun }
3902*4882a593Smuzhiyun 
ipsec_pfkey_init(void)3903*4882a593Smuzhiyun static int __init ipsec_pfkey_init(void)
3904*4882a593Smuzhiyun {
3905*4882a593Smuzhiyun 	int err = proto_register(&key_proto, 0);
3906*4882a593Smuzhiyun 
3907*4882a593Smuzhiyun 	if (err != 0)
3908*4882a593Smuzhiyun 		goto out;
3909*4882a593Smuzhiyun 
3910*4882a593Smuzhiyun 	err = register_pernet_subsys(&pfkey_net_ops);
3911*4882a593Smuzhiyun 	if (err != 0)
3912*4882a593Smuzhiyun 		goto out_unregister_key_proto;
3913*4882a593Smuzhiyun 	err = sock_register(&pfkey_family_ops);
3914*4882a593Smuzhiyun 	if (err != 0)
3915*4882a593Smuzhiyun 		goto out_unregister_pernet;
3916*4882a593Smuzhiyun 	err = xfrm_register_km(&pfkeyv2_mgr);
3917*4882a593Smuzhiyun 	if (err != 0)
3918*4882a593Smuzhiyun 		goto out_sock_unregister;
3919*4882a593Smuzhiyun out:
3920*4882a593Smuzhiyun 	return err;
3921*4882a593Smuzhiyun 
3922*4882a593Smuzhiyun out_sock_unregister:
3923*4882a593Smuzhiyun 	sock_unregister(PF_KEY);
3924*4882a593Smuzhiyun out_unregister_pernet:
3925*4882a593Smuzhiyun 	unregister_pernet_subsys(&pfkey_net_ops);
3926*4882a593Smuzhiyun out_unregister_key_proto:
3927*4882a593Smuzhiyun 	proto_unregister(&key_proto);
3928*4882a593Smuzhiyun 	goto out;
3929*4882a593Smuzhiyun }
3930*4882a593Smuzhiyun 
3931*4882a593Smuzhiyun module_init(ipsec_pfkey_init);
3932*4882a593Smuzhiyun module_exit(ipsec_pfkey_exit);
3933*4882a593Smuzhiyun MODULE_LICENSE("GPL");
3934*4882a593Smuzhiyun MODULE_ALIAS_NETPROTO(PF_KEY);
3935