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