1240116Smarcel/* $NetBSD: keysock.c,v 1.53 2009/05/09 11:36:17 mlelstv Exp $ */ 2240116Smarcel/* $KAME: keysock.c,v 1.32 2003/08/22 05:45:08 itojun Exp $ */ 3240116Smarcel 4240116Smarcel/* 5240116Smarcel * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6240116Smarcel * All rights reserved. 7240116Smarcel * 8240116Smarcel * Redistribution and use in source and binary forms, with or without 9240116Smarcel * modification, are permitted provided that the following conditions 10240116Smarcel * are met: 11240116Smarcel * 1. Redistributions of source code must retain the above copyright 12240116Smarcel * notice, this list of conditions and the following disclaimer. 13240116Smarcel * 2. Redistributions in binary form must reproduce the above copyright 14240116Smarcel * notice, this list of conditions and the following disclaimer in the 15240116Smarcel * documentation and/or other materials provided with the distribution. 16240116Smarcel * 3. Neither the name of the project nor the names of its contributors 17240116Smarcel * may be used to endorse or promote products derived from this software 18240116Smarcel * without specific prior written permission. 19240116Smarcel * 20240116Smarcel * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21240116Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22240116Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23240116Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24240116Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25240116Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26275988Sngie * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27240116Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28240116Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29240116Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30240116Smarcel * SUCH DAMAGE. 31240116Smarcel */ 32240116Smarcel 33240116Smarcel#include <sys/cdefs.h> 34240116Smarcel__KERNEL_RCSID(0, "$NetBSD: keysock.c,v 1.53 2009/05/09 11:36:17 mlelstv Exp $"); 35240116Smarcel 36240116Smarcel#include "opt_inet.h" 37240116Smarcel 38240116Smarcel/* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */ 39240116Smarcel 40240116Smarcel#include <sys/param.h> 41240116Smarcel#include <sys/systm.h> 42240116Smarcel#include <sys/kernel.h> 43240116Smarcel#include <sys/mbuf.h> 44240116Smarcel#include <sys/socket.h> 45240116Smarcel#include <sys/socketvar.h> 46240116Smarcel#include <sys/domain.h> 47240116Smarcel#include <sys/protosw.h> 48240116Smarcel#include <sys/errno.h> 49#include <sys/proc.h> 50#include <sys/queue.h> 51 52#include <net/raw_cb.h> 53#include <net/route.h> 54#include <netinet/in.h> 55 56#include <net/pfkeyv2.h> 57#include <netkey/keydb.h> 58#include <netkey/key.h> 59#include <netkey/keysock.h> 60#include <netkey/key_debug.h> 61#include <netkey/key_private.h> 62 63struct sockaddr key_dst = { .sa_len = 2, .sa_family = PF_KEY, }; 64struct sockaddr key_src = { .sa_len = 2, .sa_family = PF_KEY, }; 65 66static int key_receive(struct socket *, struct mbuf **, struct uio *, 67 struct mbuf **, struct mbuf **, int *); 68 69static int key_sendup0(struct rawcb *, struct mbuf *, int, int); 70 71static int 72key_receive(struct socket *so, struct mbuf **paddr, struct uio *uio, 73 struct mbuf **mp0, struct mbuf **controlp, int *flagsp) 74{ 75 struct rawcb *rp = sotorawcb(so); 76 struct keycb *kp = (struct keycb *)rp; 77 int error; 78 79 error = (*kp->kp_receive)(so, paddr, uio, mp0, controlp, flagsp); 80 81 /* 82 * now we might have enough receive buffer space. 83 * pull packets from kp_queue as many as possible. 84 */ 85 mutex_enter(softnet_lock); 86 KERNEL_LOCK(1, NULL); 87 while (/*CONSTCOND*/ 1) { 88 struct mbuf *m; 89 90 m = kp->kp_queue; 91 if (m == NULL || sbspace(&so->so_rcv) < m->m_pkthdr.len) 92 break; 93 kp->kp_queue = m->m_nextpkt; 94 m->m_nextpkt = NULL; /* safety */ 95 if (key_sendup0(rp, m, 0, 1)) 96 break; 97 } 98 KERNEL_UNLOCK_ONE(NULL); 99 mutex_exit(softnet_lock); 100 101 return error; 102} 103 104/* 105 * key_usrreq() 106 * derived from net/rtsock.c:route_usrreq() 107 */ 108int 109key_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, struct mbuf *control, struct lwp *l) 110{ 111 int error = 0; 112 struct keycb *kp = (struct keycb *)sotorawcb(so); 113 int s; 114 115 s = splsoftnet(); 116 if (req == PRU_ATTACH) { 117 sosetlock(so); 118 kp = (struct keycb *)malloc(sizeof(*kp), M_PCB, 119 M_WAITOK|M_ZERO); 120 so->so_pcb = (void *)kp; 121 kp->kp_receive = so->so_receive; 122 so->so_receive = key_receive; 123 } 124 if (req == PRU_DETACH && kp) { 125 int af = kp->kp_raw.rcb_proto.sp_protocol; 126 struct mbuf *n; 127 128 if (af == PF_KEY) 129 key_cb.key_count--; 130 key_cb.any_count--; 131 132 key_freereg(so); 133 134 while (kp->kp_queue) { 135 n = kp->kp_queue->m_nextpkt; 136 kp->kp_queue->m_nextpkt = NULL; 137 m_freem(kp->kp_queue); 138 kp->kp_queue = n; 139 } 140 } 141 142 error = raw_usrreq(so, req, m, nam, control, l); 143 m = control = NULL; /* reclaimed in raw_usrreq */ 144 kp = (struct keycb *)sotorawcb(so); 145 if (req == PRU_ATTACH && kp) { 146 int af = kp->kp_raw.rcb_proto.sp_protocol; 147 if (error) { 148 PFKEY_STATINC(PFKEY_STAT_SOCKERR); 149 free((void *)kp, M_PCB); 150 so->so_pcb = (void *) 0; 151 splx(s); 152 return (error); 153 } 154 155 kp->kp_promisc = kp->kp_registered = 0; 156 157 if (af == PF_KEY) 158 key_cb.key_count++; 159 key_cb.any_count++; 160 kp->kp_raw.rcb_laddr = &key_src; 161 kp->kp_raw.rcb_faddr = &key_dst; 162 soisconnected(so); 163 so->so_options |= SO_USELOOPBACK; 164 } 165 splx(s); 166 return (error); 167} 168 169/* 170 * key_output() 171 */ 172int 173key_output(struct mbuf *m, ...) 174{ 175 struct sadb_msg *msg; 176 int len, error = 0; 177 int s; 178 struct socket *so; 179 va_list ap; 180 181 va_start(ap, m); 182 so = va_arg(ap, struct socket *); 183 va_end(ap); 184 185 if (m == 0) 186 panic("key_output: NULL pointer was passed."); 187 188 { 189 uint64_t *ps = PFKEY_STAT_GETREF(); 190 ps[PFKEY_STAT_OUT_TOTAL]++; 191 ps[PFKEY_STAT_OUT_BYTES] += m->m_pkthdr.len; 192 PFKEY_STAT_PUTREF(); 193 } 194 195 len = m->m_pkthdr.len; 196 if (len < sizeof(struct sadb_msg)) { 197 PFKEY_STATINC(PFKEY_STAT_OUT_TOOSHORT); 198 error = EINVAL; 199 goto end; 200 } 201 202 if (m->m_len < sizeof(struct sadb_msg)) { 203 if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) { 204 PFKEY_STATINC(PFKEY_STAT_OUT_NOMEM); 205 error = ENOBUFS; 206 goto end; 207 } 208 } 209 210 if ((m->m_flags & M_PKTHDR) == 0) 211 panic("key_output: not M_PKTHDR ??"); 212 213 KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m)); 214 215 msg = mtod(m, struct sadb_msg *); 216 PFKEY_STATINC(PFKEY_STAT_OUT_MSGTYPE + msg->sadb_msg_type); 217 if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) { 218 PFKEY_STATINC(PFKEY_STAT_OUT_INVLEN); 219 error = EINVAL; 220 goto end; 221 } 222 223 /*XXX giant lock*/ 224 s = splsoftnet(); 225 error = key_parse(m, so); 226 m = NULL; 227 splx(s); 228end: 229 if (m) 230 m_freem(m); 231 return error; 232} 233 234/* 235 * send message to the socket. 236 */ 237static int 238key_sendup0(struct rawcb *rp, struct mbuf *m, int promisc, int canwait) 239{ 240 struct keycb *kp = (struct keycb *)rp; 241 struct mbuf *n; 242 int error = 0; 243 244 if (promisc) { 245 struct sadb_msg *pmsg; 246 247 M_PREPEND(m, sizeof(struct sadb_msg), M_NOWAIT); 248 if (m && m->m_len < sizeof(struct sadb_msg)) 249 m = m_pullup(m, sizeof(struct sadb_msg)); 250 if (!m) { 251 PFKEY_STATINC(PFKEY_STAT_OUT_NOMEM); 252 return ENOBUFS; 253 } 254 m->m_pkthdr.len += sizeof(*pmsg); 255 256 pmsg = mtod(m, struct sadb_msg *); 257 memset(pmsg, 0, sizeof(*pmsg)); 258 pmsg->sadb_msg_version = PF_KEY_V2; 259 pmsg->sadb_msg_type = SADB_X_PROMISC; 260 pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); 261 /* pid and seq? */ 262 263 PFKEY_STATINC(PFKEY_STAT_IN_MSGTYPE + pmsg->sadb_msg_type); 264 } 265 266 if (canwait) { 267 if (kp->kp_queue) { 268 for (n = kp->kp_queue; n && n->m_nextpkt; 269 n = n->m_nextpkt) 270 ; 271 n->m_nextpkt = m; 272 m = kp->kp_queue; 273 kp->kp_queue = NULL; 274 } else 275 m->m_nextpkt = NULL; /* just for safety */ 276 } else 277 m->m_nextpkt = NULL; 278 279 for (; m && error == 0; m = n) { 280 n = m->m_nextpkt; 281 282 if (canwait && 283 sbspace(&rp->rcb_socket->so_rcv) < m->m_pkthdr.len) { 284 error = EAGAIN; 285 goto recovery; 286 } 287 288 m->m_nextpkt = NULL; 289 290 if (!sbappendaddr(&rp->rcb_socket->so_rcv, 291 (struct sockaddr *)&key_src, m, NULL)) { 292 PFKEY_STATINC(PFKEY_STAT_IN_NOMEM); 293 error = ENOBUFS; 294 goto recovery; 295 } else { 296 sorwakeup(rp->rcb_socket); 297 error = 0; 298 } 299 } 300 return (error); 301 302recovery: 303 if (kp->kp_queue) { 304 /* 305 * kp_queue != NULL implies !canwait. 306 */ 307 KASSERT(!canwait); 308 KASSERT(m->m_nextpkt == NULL); 309 /* 310 * insert m to the head of queue, as normally mbuf on the queue 311 * is less important than others. 312 */ 313 if (m) { 314 m->m_nextpkt = kp->kp_queue; 315 kp->kp_queue = m; 316 } 317 } else { 318 /* recover the queue */ 319 if (!m) { 320 /* first ENOBUFS case */ 321 kp->kp_queue = n; 322 } else { 323 kp->kp_queue = m; 324 m->m_nextpkt = n; 325 } 326 } 327 return (error); 328} 329 330/* so can be NULL if target != KEY_SENDUP_ONE */ 331int 332key_sendup_mbuf(struct socket *so, struct mbuf *m, int target) 333{ 334 struct mbuf *n; 335 struct keycb *kp; 336 int sendup; 337 struct rawcb *rp; 338 int error = 0; 339 int canwait; 340 341 if (m == NULL) 342 panic("key_sendup_mbuf: NULL pointer was passed."); 343 if (so == NULL && target == KEY_SENDUP_ONE) 344 panic("key_sendup_mbuf: NULL pointer was passed."); 345 346 canwait = target & KEY_SENDUP_CANWAIT; 347 target &= ~KEY_SENDUP_CANWAIT; 348 349 { 350 uint64_t *ps = PFKEY_STAT_GETREF(); 351 ps[PFKEY_STAT_IN_TOTAL]++; 352 ps[PFKEY_STAT_IN_BYTES] += m->m_pkthdr.len; 353 PFKEY_STAT_PUTREF(); 354 } 355 if (m->m_len < sizeof(struct sadb_msg)) { 356 m = m_pullup(m, sizeof(struct sadb_msg)); 357 if (m == NULL) { 358 PFKEY_STATINC(PFKEY_STAT_IN_NOMEM); 359 return ENOBUFS; 360 } 361 } 362 if (m->m_len >= sizeof(struct sadb_msg)) { 363 struct sadb_msg *msg; 364 msg = mtod(m, struct sadb_msg *); 365 PFKEY_STATINC(PFKEY_STAT_IN_MSGTYPE + msg->sadb_msg_type); 366 } 367 368 for (rp = rawcb.lh_first; rp; rp = rp->rcb_list.le_next) 369 { 370 if (rp->rcb_proto.sp_family != PF_KEY) 371 continue; 372 if (rp->rcb_proto.sp_protocol && 373 rp->rcb_proto.sp_protocol != PF_KEY_V2) { 374 continue; 375 } 376 377 kp = (struct keycb *)rp; 378 379 /* 380 * If you are in promiscuous mode, and when you get broadcasted 381 * reply, you'll get two PF_KEY messages. 382 * (based on pf_key@inner.net message on 14 Oct 1998) 383 */ 384 if (((struct keycb *)rp)->kp_promisc) { 385 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { 386 (void)key_sendup0(rp, n, 1, canwait); 387 n = NULL; 388 } 389 } 390 391 /* the exact target will be processed later */ 392 if (so && sotorawcb(so) == rp) 393 continue; 394 395 sendup = 0; 396 switch (target) { 397 case KEY_SENDUP_ONE: 398 /* the statement has no effect */ 399 if (so && sotorawcb(so) == rp) 400 sendup++; 401 break; 402 case KEY_SENDUP_ALL: 403 sendup++; 404 break; 405 case KEY_SENDUP_REGISTERED: 406 if (kp->kp_registered) 407 sendup++; 408 break; 409 } 410 PFKEY_STATINC(PFKEY_STAT_IN_MSGTARGET + target); 411 412 if (!sendup) 413 continue; 414 415 if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) { 416 m_freem(m); 417 PFKEY_STATINC(PFKEY_STAT_IN_NOMEM); 418 return ENOBUFS; 419 } 420 421 /* 422 * ignore error even if queue is full. PF_KEY does not 423 * guarantee the delivery of the message. 424 * this is important when target == KEY_SENDUP_ALL. 425 */ 426 key_sendup0(rp, n, 0, canwait); 427 428 n = NULL; 429 } 430 431 if (so) { 432 error = key_sendup0(sotorawcb(so), m, 0, canwait); 433 m = NULL; 434 } else { 435 error = 0; 436 m_freem(m); 437 } 438 return error; 439} 440 441 442/* 443 * Definitions of protocols supported in the KEY domain. 444 */ 445 446DOMAIN_DEFINE(keydomain); 447 448PR_WRAP_USRREQ(key_usrreq) 449 450#define key_usrreq key_usrreq_wrapper 451 452const struct protosw keysw[] = { 453{ .pr_type = SOCK_RAW, 454 .pr_domain = &keydomain, 455 .pr_protocol = PF_KEY_V2, 456 .pr_flags = PR_ATOMIC|PR_ADDR, 457 .pr_input = 0, 458 .pr_output = key_output, 459 .pr_ctlinput = raw_ctlinput, 460 .pr_ctloutput = 0, 461 .pr_usrreq = key_usrreq, 462 .pr_init = raw_init, 463 .pr_fasttimo = 0, 464 .pr_slowtimo = 0, 465 .pr_drain = 0, 466} 467}; 468 469struct domain keydomain = { 470 .dom_family = PF_KEY, 471 .dom_name = "key", 472 .dom_init = key_init, 473 .dom_protosw = keysw, 474 .dom_protoswNPROTOSW = &keysw[sizeof(keysw)/sizeof(keysw[0])], 475}; 476