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