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 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 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 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 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 292 key_close(struct socket *so) 293 { 294 295 soisdisconnected(so); 296 } 297 298 static void 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 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