xref: /freebsd/sys/netipsec/keysock.c (revision e453e498cbb88570a3ff7b3679de65c88707da95)
1 /*	$KAME: keysock.c,v 1.25 2001/08/13 20:07:41 itojun Exp $	*/
2 
3 /*-
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the project nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include "opt_ipsec.h"
35 
36 /* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */
37 
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/domain.h>
41 #include <sys/errno.h>
42 #include <sys/kernel.h>
43 #include <sys/lock.h>
44 #include <sys/malloc.h>
45 #include <sys/mbuf.h>
46 #include <sys/mutex.h>
47 #include <sys/priv.h>
48 #include <sys/protosw.h>
49 #include <sys/signalvar.h>
50 #include <sys/socket.h>
51 #include <sys/socketvar.h>
52 #include <sys/stdarg.h>
53 #include <sys/sysctl.h>
54 #include <sys/systm.h>
55 
56 #include <net/if.h>
57 #include <net/vnet.h>
58 
59 #include <netinet/in.h>
60 
61 #include <net/pfkeyv2.h>
62 #include <netipsec/key.h>
63 #include <netipsec/keysock.h>
64 #include <netipsec/key_debug.h>
65 #include <netipsec/ipsec.h>
66 
67 static struct mtx keysock_mtx;
68 MTX_SYSINIT(keysock, &keysock_mtx, "key socket pcb list", MTX_DEF);
69 
70 #define	KEYSOCK_LOCK()		mtx_lock(&keysock_mtx)
71 #define	KEYSOCK_UNLOCK()	mtx_unlock(&keysock_mtx)
72 
73 VNET_DEFINE_STATIC(LIST_HEAD(, keycb), keycb_list) =
74     LIST_HEAD_INITIALIZER(keycb_list);
75 #define	V_keycb_list		VNET(keycb_list)
76 
77 static struct sockaddr key_src = { 2, PF_KEY, };
78 
79 static int key_sendup0(struct keycb *, struct mbuf *, int);
80 
81 VNET_PCPUSTAT_DEFINE(struct pfkeystat, pfkeystat);
82 VNET_PCPUSTAT_SYSINIT(pfkeystat);
83 
84 #ifdef VIMAGE
85 VNET_PCPUSTAT_SYSUNINIT(pfkeystat);
86 #endif /* VIMAGE */
87 
88 static int
key_send(struct socket * so,int flags,struct mbuf * m,struct sockaddr * nam,struct mbuf * control,struct thread * td)89 key_send(struct socket *so, int flags, struct mbuf *m,
90     struct sockaddr *nam, struct mbuf *control, struct thread *td)
91 {
92 	struct sadb_msg *msg;
93 	int len, error = 0;
94 
95 	if ((flags & PRUS_OOB) || control != NULL) {
96 		m_freem(m);
97 		if (control != NULL)
98 			m_freem(control);
99 		return (EOPNOTSUPP);
100 	}
101 
102 	PFKEYSTAT_INC(out_total);
103 	PFKEYSTAT_ADD(out_bytes, m->m_pkthdr.len);
104 
105 	len = m->m_pkthdr.len;
106 	if (len < sizeof(struct sadb_msg)) {
107 		PFKEYSTAT_INC(out_tooshort);
108 		error = EINVAL;
109 		goto end;
110 	}
111 
112 	if (m->m_len < sizeof(struct sadb_msg)) {
113 		if ((m = m_pullup(m, sizeof(struct sadb_msg))) == NULL) {
114 			PFKEYSTAT_INC(out_nomem);
115 			error = ENOBUFS;
116 			goto end;
117 		}
118 	}
119 
120 	M_ASSERTPKTHDR(m);
121 
122 	KEYDBG(KEY_DUMP, kdebug_mbuf(m));
123 
124 	msg = mtod(m, struct sadb_msg *);
125 	PFKEYSTAT_INC(out_msgtype[msg->sadb_msg_type]);
126 	if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) {
127 		PFKEYSTAT_INC(out_invlen);
128 		error = EINVAL;
129 		goto end;
130 	}
131 
132 	error = key_parse(m, so);
133 	m = NULL;
134 end:
135 	if (m != NULL)
136 		m_freem(m);
137 	return (error);
138 }
139 
140 /*
141  * send message to the socket.
142  */
143 static int
key_sendup0(struct keycb * kp,struct mbuf * m,int promisc)144 key_sendup0(struct keycb *kp, struct mbuf *m, int promisc)
145 {
146 
147 	if (promisc) {
148 		struct sadb_msg *pmsg;
149 
150 		M_PREPEND(m, sizeof(struct sadb_msg), M_NOWAIT);
151 		if (m == NULL) {
152 			PFKEYSTAT_INC(in_nomem);
153 			return (ENOBUFS);
154 		}
155 		pmsg = mtod(m, struct sadb_msg *);
156 		bzero(pmsg, sizeof(*pmsg));
157 		pmsg->sadb_msg_version = PF_KEY_V2;
158 		pmsg->sadb_msg_type = SADB_X_PROMISC;
159 		pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
160 		/* pid and seq? */
161 
162 		PFKEYSTAT_INC(in_msgtype[pmsg->sadb_msg_type]);
163 	}
164 
165 	if (!sbappendaddr(&kp->kp_socket->so_rcv, &key_src, m, NULL)) {
166 		PFKEYSTAT_INC(in_nomem);
167 		m_freem(m);
168 		soroverflow(kp->kp_socket);
169 		return (ENOBUFS);
170 	}
171 
172 	sorwakeup(kp->kp_socket);
173 	return (0);
174 }
175 
176 /* so can be NULL if target != KEY_SENDUP_ONE */
177 int
key_sendup_mbuf(struct socket * so,struct mbuf * m,int target)178 key_sendup_mbuf(struct socket *so, struct mbuf *m, int target)
179 {
180 	struct mbuf *n;
181 	struct keycb *kp;
182 	int error = 0;
183 
184 	KASSERT(m != NULL, ("NULL mbuf pointer was passed."));
185 	KASSERT(so != NULL || target != KEY_SENDUP_ONE,
186 	    ("NULL socket pointer was passed."));
187 	KASSERT(target == KEY_SENDUP_ONE || target == KEY_SENDUP_ALL ||
188 	    target == KEY_SENDUP_REGISTERED, ("Wrong target %d", target));
189 
190 	PFKEYSTAT_INC(in_total);
191 	PFKEYSTAT_ADD(in_bytes, m->m_pkthdr.len);
192 	if (m->m_len < sizeof(struct sadb_msg)) {
193 		m = m_pullup(m, sizeof(struct sadb_msg));
194 		if (m == NULL) {
195 			PFKEYSTAT_INC(in_nomem);
196 			return (ENOBUFS);
197 		}
198 	}
199 	if (m->m_len >= sizeof(struct sadb_msg)) {
200 		struct sadb_msg *msg;
201 		msg = mtod(m, struct sadb_msg *);
202 		PFKEYSTAT_INC(in_msgtype[msg->sadb_msg_type]);
203 	}
204 	KEYSOCK_LOCK();
205 	LIST_FOREACH(kp, &V_keycb_list, kp_next) {
206 		/*
207 		 * If you are in promiscuous mode, and when you get broadcasted
208 		 * reply, you'll get two PF_KEY messages.
209 		 * (based on pf_key@inner.net message on 14 Oct 1998)
210 		 */
211 		if (kp->kp_promisc) {
212 			n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
213 			if (n != NULL)
214 				key_sendup0(kp, n, 1);
215 			else
216 				PFKEYSTAT_INC(in_nomem);
217 		}
218 
219 		/* the exact target will be processed later */
220 		if (so != NULL && so->so_pcb == kp)
221 			continue;
222 
223 		if (target == KEY_SENDUP_ONE || (target ==
224 		    KEY_SENDUP_REGISTERED && kp->kp_registered == 0))
225 			continue;
226 
227 		/* KEY_SENDUP_ALL + KEY_SENDUP_REGISTERED */
228 		n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
229 		if (n == NULL) {
230 			PFKEYSTAT_INC(in_nomem);
231 			/* Try send to another socket */
232 			continue;
233 		}
234 
235 		if (key_sendup0(kp, n, 0) == 0)
236 			PFKEYSTAT_INC(in_msgtarget[target]);
237 	}
238 
239 	if (so)	{ /* KEY_SENDUP_ONE */
240 		error = key_sendup0(so->so_pcb, m, 0);
241 		if (error == 0)
242 			PFKEYSTAT_INC(in_msgtarget[KEY_SENDUP_ONE]);
243 	} else {
244 		error = 0;
245 		m_freem(m);
246 	}
247 	KEYSOCK_UNLOCK();
248 	return (error);
249 }
250 
251 static u_long key_sendspace = 8192;
252 SYSCTL_ULONG(_net_key, OID_AUTO, sendspace, CTLFLAG_RW, &key_sendspace, 0,
253     "Default key socket send space");
254 static u_long key_recvspace = 8192;
255 SYSCTL_ULONG(_net_key, OID_AUTO, recvspace, CTLFLAG_RW, &key_recvspace, 0,
256     "Default key socket receive space");
257 
258 static int
key_attach(struct socket * so,int proto,struct thread * td)259 key_attach(struct socket *so, int proto, struct thread *td)
260 {
261 	struct keycb *kp;
262 	int error;
263 
264 	KASSERT(so->so_pcb == NULL, ("key_attach: so_pcb != NULL"));
265 
266 	if (td != NULL) {
267 		error = priv_check(td, PRIV_NET_RAW);
268 		if (error != 0)
269 			return (error);
270 	}
271 
272 	error = soreserve(so, key_sendspace, key_recvspace);
273 	if (error != 0)
274 		return (error);
275 
276 	kp = malloc(sizeof(*kp), M_PCB, M_WAITOK);
277 	kp->kp_socket = so;
278 	kp->kp_promisc = kp->kp_registered = 0;
279 
280 	so->so_pcb = kp;
281 	so->so_options |= SO_USELOOPBACK;
282 
283 	KEYSOCK_LOCK();
284 	LIST_INSERT_HEAD(&V_keycb_list, kp, kp_next);
285 	KEYSOCK_UNLOCK();
286 	soisconnected(so);
287 
288 	return (0);
289 }
290 
291 static void
key_close(struct socket * so)292 key_close(struct socket *so)
293 {
294 
295 	soisdisconnected(so);
296 }
297 
298 static void
key_detach(struct socket * so)299 key_detach(struct socket *so)
300 {
301 	struct keycb *kp = so->so_pcb;
302 
303 	key_freereg(so);
304 	KEYSOCK_LOCK();
305 	LIST_REMOVE(kp, kp_next);
306 	KEYSOCK_UNLOCK();
307 	free(kp, M_PCB);
308 	so->so_pcb = NULL;
309 }
310 
311 static int
key_shutdown(struct socket * so,enum shutdown_how how)312 key_shutdown(struct socket *so, enum shutdown_how how)
313 {
314 	/*
315 	 * Note: key socket marks itself as connected through its lifetime.
316 	 */
317 	switch (how) {
318 	case SHUT_RD:
319 		socantrcvmore(so);
320 		sbrelease(so, SO_RCV);
321 		break;
322 	case SHUT_RDWR:
323 		socantrcvmore(so);
324 		sbrelease(so, SO_RCV);
325 		/* FALLTHROUGH */
326 	case SHUT_WR:
327 		socantsendmore(so);
328 	}
329 
330 	return (0);
331 }
332 
333 SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
334     "Key Family");
335 
336 static struct protosw keysw = {
337 	.pr_type =		SOCK_RAW,
338 	.pr_protocol =		PF_KEY_V2,
339 	.pr_flags =		PR_ATOMIC | PR_ADDR,
340 	.pr_abort =		key_close,
341 	.pr_attach =		key_attach,
342 	.pr_detach =		key_detach,
343 	.pr_send =		key_send,
344 	.pr_shutdown =		key_shutdown,
345 	.pr_close =		key_close,
346 };
347 
348 static struct domain keydomain = {
349 	.dom_family =		PF_KEY,
350 	.dom_name =		"key",
351 	.dom_nprotosw =		1,
352 	.dom_protosw =		{ &keysw },
353 };
354 DOMAIN_SET(key);
355