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/sysctl.h> 53 #include <sys/systm.h> 54 55 #include <net/if.h> 56 #include <net/vnet.h> 57 58 #include <netinet/in.h> 59 60 #include <net/pfkeyv2.h> 61 #include <netipsec/key.h> 62 #include <netipsec/keysock.h> 63 #include <netipsec/key_debug.h> 64 #include <netipsec/ipsec.h> 65 66 #include <machine/stdarg.h> 67 68 static struct mtx keysock_mtx; 69 MTX_SYSINIT(keysock, &keysock_mtx, "key socket pcb list", MTX_DEF); 70 71 #define KEYSOCK_LOCK() mtx_lock(&keysock_mtx) 72 #define KEYSOCK_UNLOCK() mtx_unlock(&keysock_mtx) 73 74 VNET_DEFINE_STATIC(LIST_HEAD(, keycb), keycb_list) = 75 LIST_HEAD_INITIALIZER(keycb_list); 76 #define V_keycb_list VNET(keycb_list) 77 78 static struct sockaddr key_src = { 2, PF_KEY, }; 79 80 static int key_sendup0(struct keycb *, struct mbuf *, int); 81 82 VNET_PCPUSTAT_DEFINE(struct pfkeystat, pfkeystat); 83 VNET_PCPUSTAT_SYSINIT(pfkeystat); 84 85 #ifdef VIMAGE 86 VNET_PCPUSTAT_SYSUNINIT(pfkeystat); 87 #endif /* VIMAGE */ 88 89 static int 90 key_send(struct socket *so, int flags, struct mbuf *m, 91 struct sockaddr *nam, struct mbuf *control, struct thread *td) 92 { 93 struct sadb_msg *msg; 94 int len, error = 0; 95 96 if ((flags & PRUS_OOB) || control != NULL) { 97 m_freem(m); 98 if (control != NULL) 99 m_freem(control); 100 return (EOPNOTSUPP); 101 } 102 103 PFKEYSTAT_INC(out_total); 104 PFKEYSTAT_ADD(out_bytes, m->m_pkthdr.len); 105 106 len = m->m_pkthdr.len; 107 if (len < sizeof(struct sadb_msg)) { 108 PFKEYSTAT_INC(out_tooshort); 109 error = EINVAL; 110 goto end; 111 } 112 113 if (m->m_len < sizeof(struct sadb_msg)) { 114 if ((m = m_pullup(m, sizeof(struct sadb_msg))) == NULL) { 115 PFKEYSTAT_INC(out_nomem); 116 error = ENOBUFS; 117 goto end; 118 } 119 } 120 121 M_ASSERTPKTHDR(m); 122 123 KEYDBG(KEY_DUMP, kdebug_mbuf(m)); 124 125 msg = mtod(m, struct sadb_msg *); 126 PFKEYSTAT_INC(out_msgtype[msg->sadb_msg_type]); 127 if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) { 128 PFKEYSTAT_INC(out_invlen); 129 error = EINVAL; 130 goto end; 131 } 132 133 error = key_parse(m, so); 134 m = NULL; 135 end: 136 if (m != NULL) 137 m_freem(m); 138 return (error); 139 } 140 141 /* 142 * send message to the socket. 143 */ 144 static int 145 key_sendup0(struct keycb *kp, struct mbuf *m, int promisc) 146 { 147 148 if (promisc) { 149 struct sadb_msg *pmsg; 150 151 M_PREPEND(m, sizeof(struct sadb_msg), M_NOWAIT); 152 if (m == NULL) { 153 PFKEYSTAT_INC(in_nomem); 154 return (ENOBUFS); 155 } 156 pmsg = mtod(m, struct sadb_msg *); 157 bzero(pmsg, sizeof(*pmsg)); 158 pmsg->sadb_msg_version = PF_KEY_V2; 159 pmsg->sadb_msg_type = SADB_X_PROMISC; 160 pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); 161 /* pid and seq? */ 162 163 PFKEYSTAT_INC(in_msgtype[pmsg->sadb_msg_type]); 164 } 165 166 if (!sbappendaddr(&kp->kp_socket->so_rcv, &key_src, m, NULL)) { 167 PFKEYSTAT_INC(in_nomem); 168 m_freem(m); 169 soroverflow(kp->kp_socket); 170 return (ENOBUFS); 171 } 172 173 sorwakeup(kp->kp_socket); 174 return (0); 175 } 176 177 /* so can be NULL if target != KEY_SENDUP_ONE */ 178 int 179 key_sendup_mbuf(struct socket *so, struct mbuf *m, int target) 180 { 181 struct mbuf *n; 182 struct keycb *kp; 183 int error = 0; 184 185 KASSERT(m != NULL, ("NULL mbuf pointer was passed.")); 186 KASSERT(so != NULL || target != KEY_SENDUP_ONE, 187 ("NULL socket pointer was passed.")); 188 KASSERT(target == KEY_SENDUP_ONE || target == KEY_SENDUP_ALL || 189 target == KEY_SENDUP_REGISTERED, ("Wrong target %d", target)); 190 191 PFKEYSTAT_INC(in_total); 192 PFKEYSTAT_ADD(in_bytes, m->m_pkthdr.len); 193 if (m->m_len < sizeof(struct sadb_msg)) { 194 m = m_pullup(m, sizeof(struct sadb_msg)); 195 if (m == NULL) { 196 PFKEYSTAT_INC(in_nomem); 197 return (ENOBUFS); 198 } 199 } 200 if (m->m_len >= sizeof(struct sadb_msg)) { 201 struct sadb_msg *msg; 202 msg = mtod(m, struct sadb_msg *); 203 PFKEYSTAT_INC(in_msgtype[msg->sadb_msg_type]); 204 } 205 KEYSOCK_LOCK(); 206 LIST_FOREACH(kp, &V_keycb_list, kp_next) { 207 /* 208 * If you are in promiscuous mode, and when you get broadcasted 209 * reply, you'll get two PF_KEY messages. 210 * (based on pf_key@inner.net message on 14 Oct 1998) 211 */ 212 if (kp->kp_promisc) { 213 n = m_copym(m, 0, M_COPYALL, M_NOWAIT); 214 if (n != NULL) 215 key_sendup0(kp, n, 1); 216 else 217 PFKEYSTAT_INC(in_nomem); 218 } 219 220 /* the exact target will be processed later */ 221 if (so != NULL && so->so_pcb == kp) 222 continue; 223 224 if (target == KEY_SENDUP_ONE || (target == 225 KEY_SENDUP_REGISTERED && kp->kp_registered == 0)) 226 continue; 227 228 /* KEY_SENDUP_ALL + KEY_SENDUP_REGISTERED */ 229 n = m_copym(m, 0, M_COPYALL, M_NOWAIT); 230 if (n == NULL) { 231 PFKEYSTAT_INC(in_nomem); 232 /* Try send to another socket */ 233 continue; 234 } 235 236 if (key_sendup0(kp, n, 0) == 0) 237 PFKEYSTAT_INC(in_msgtarget[target]); 238 } 239 240 if (so) { /* KEY_SENDUP_ONE */ 241 error = key_sendup0(so->so_pcb, m, 0); 242 if (error == 0) 243 PFKEYSTAT_INC(in_msgtarget[KEY_SENDUP_ONE]); 244 } else { 245 error = 0; 246 m_freem(m); 247 } 248 KEYSOCK_UNLOCK(); 249 return (error); 250 } 251 252 static u_long key_sendspace = 8192; 253 SYSCTL_ULONG(_net_key, OID_AUTO, sendspace, CTLFLAG_RW, &key_sendspace, 0, 254 "Default key socket send space"); 255 static u_long key_recvspace = 8192; 256 SYSCTL_ULONG(_net_key, OID_AUTO, recvspace, CTLFLAG_RW, &key_recvspace, 0, 257 "Default key socket receive space"); 258 259 static int 260 key_attach(struct socket *so, int proto, struct thread *td) 261 { 262 struct keycb *kp; 263 int error; 264 265 KASSERT(so->so_pcb == NULL, ("key_attach: so_pcb != NULL")); 266 267 if (td != NULL) { 268 error = priv_check(td, PRIV_NET_RAW); 269 if (error != 0) 270 return (error); 271 } 272 273 error = soreserve(so, key_sendspace, key_recvspace); 274 if (error != 0) 275 return (error); 276 277 kp = malloc(sizeof(*kp), M_PCB, M_WAITOK); 278 kp->kp_socket = so; 279 kp->kp_promisc = kp->kp_registered = 0; 280 281 so->so_pcb = kp; 282 so->so_options |= SO_USELOOPBACK; 283 284 KEYSOCK_LOCK(); 285 LIST_INSERT_HEAD(&V_keycb_list, kp, kp_next); 286 KEYSOCK_UNLOCK(); 287 soisconnected(so); 288 289 return (0); 290 } 291 292 static void 293 key_close(struct socket *so) 294 { 295 296 soisdisconnected(so); 297 } 298 299 static void 300 key_detach(struct socket *so) 301 { 302 struct keycb *kp = so->so_pcb; 303 304 key_freereg(so); 305 KEYSOCK_LOCK(); 306 LIST_REMOVE(kp, kp_next); 307 KEYSOCK_UNLOCK(); 308 free(kp, M_PCB); 309 so->so_pcb = NULL; 310 } 311 312 static int 313 key_shutdown(struct socket *so, enum shutdown_how how) 314 { 315 /* 316 * Note: key socket marks itself as connected through its lifetime. 317 */ 318 switch (how) { 319 case SHUT_RD: 320 socantrcvmore(so); 321 sbrelease(so, SO_RCV); 322 break; 323 case SHUT_RDWR: 324 socantrcvmore(so); 325 sbrelease(so, SO_RCV); 326 /* FALLTHROUGH */ 327 case SHUT_WR: 328 socantsendmore(so); 329 } 330 331 return (0); 332 } 333 334 SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 335 "Key Family"); 336 337 static struct protosw keysw = { 338 .pr_type = SOCK_RAW, 339 .pr_protocol = PF_KEY_V2, 340 .pr_flags = PR_ATOMIC | PR_ADDR, 341 .pr_abort = key_close, 342 .pr_attach = key_attach, 343 .pr_detach = key_detach, 344 .pr_send = key_send, 345 .pr_shutdown = key_shutdown, 346 .pr_close = key_close, 347 }; 348 349 static struct domain keydomain = { 350 .dom_family = PF_KEY, 351 .dom_name = "key", 352 .dom_nprotosw = 1, 353 .dom_protosw = { &keysw }, 354 }; 355 DOMAIN_SET(key); 356