1 /* $NetBSD: keysock.c,v 1.4 2004/04/26 01:41:15 matt Exp $ */ 2 /* $FreeBSD: src/sys/netipsec/keysock.c,v 1.3.2.1 2003/01/24 05:11:36 sam Exp $ */ 3 /* $KAME: keysock.c,v 1.25 2001/08/13 20:07:41 itojun Exp $ */ 4 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 <sys/cdefs.h> 35 __KERNEL_RCSID(0, "$NetBSD: keysock.c,v 1.4 2004/04/26 01:41:15 matt Exp $"); 36 37 #include "opt_ipsec.h" 38 39 /* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */ 40 41 #include <sys/types.h> 42 #include <sys/param.h> 43 #include <sys/domain.h> 44 #include <sys/errno.h> 45 #include <sys/kernel.h> 46 #include <sys/malloc.h> 47 #include <sys/mbuf.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/raw_cb.h> 56 #include <net/route.h> 57 58 #include <net/pfkeyv2.h> 59 #include <netipsec/key.h> 60 #include <netipsec/keysock.h> 61 #include <netipsec/key_debug.h> 62 63 #include <netipsec/ipsec_osdep.h> 64 65 #include <machine/stdarg.h> 66 67 typedef int pr_output_t (struct mbuf *, struct socket *); 68 69 struct key_cb { 70 int key_count; 71 int any_count; 72 }; 73 static struct key_cb key_cb; 74 75 static struct sockaddr key_dst = { 2, PF_KEY, }; 76 static struct sockaddr key_src = { 2, PF_KEY, }; 77 78 static int key_sendup0 __P((struct rawcb *, struct mbuf *, int)); 79 80 struct pfkeystat pfkeystat; 81 82 /* 83 * key_output() 84 */ 85 int 86 key_output(struct mbuf *m, ...) 87 { 88 struct sadb_msg *msg; 89 int len, error = 0; 90 int s; 91 struct socket *so; 92 va_list ap; 93 94 va_start(ap, m); 95 so = va_arg(ap, struct socket *); 96 va_end(ap); 97 98 if (m == 0) 99 panic("key_output: NULL pointer was passed.\n"); 100 101 pfkeystat.out_total++; 102 pfkeystat.out_bytes += m->m_pkthdr.len; 103 104 len = m->m_pkthdr.len; 105 if (len < sizeof(struct sadb_msg)) { 106 pfkeystat.out_tooshort++; 107 error = EINVAL; 108 goto end; 109 } 110 111 if (m->m_len < sizeof(struct sadb_msg)) { 112 if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) { 113 pfkeystat.out_nomem++; 114 error = ENOBUFS; 115 goto end; 116 } 117 } 118 119 if ((m->m_flags & M_PKTHDR) == 0) 120 panic("key_output: not M_PKTHDR ??"); 121 122 KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m)); 123 124 msg = mtod(m, struct sadb_msg *); 125 pfkeystat.out_msgtype[msg->sadb_msg_type]++; 126 if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) { 127 pfkeystat.out_invlen++; 128 error = EINVAL; 129 goto end; 130 } 131 132 /*XXX giant lock*/ 133 s = splsoftnet(); 134 error = key_parse(m, so); 135 m = NULL; 136 splx(s); 137 end: 138 if (m) 139 m_freem(m); 140 return error; 141 } 142 143 /* 144 * send message to the socket. 145 */ 146 static int 147 key_sendup0(rp, m, promisc) 148 struct rawcb *rp; 149 struct mbuf *m; 150 int promisc; 151 { 152 int error; 153 154 if (promisc) { 155 struct sadb_msg *pmsg; 156 157 M_PREPEND(m, sizeof(struct sadb_msg), M_DONTWAIT); 158 if (m && m->m_len < sizeof(struct sadb_msg)) 159 m = m_pullup(m, sizeof(struct sadb_msg)); 160 if (!m) { 161 pfkeystat.in_nomem++; 162 m_freem(m); 163 return ENOBUFS; 164 } 165 m->m_pkthdr.len += sizeof(*pmsg); 166 167 pmsg = mtod(m, struct sadb_msg *); 168 bzero(pmsg, sizeof(*pmsg)); 169 pmsg->sadb_msg_version = PF_KEY_V2; 170 pmsg->sadb_msg_type = SADB_X_PROMISC; 171 pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); 172 /* pid and seq? */ 173 174 pfkeystat.in_msgtype[pmsg->sadb_msg_type]++; 175 } 176 177 if (!sbappendaddr(&rp->rcb_socket->so_rcv, (struct sockaddr *)&key_src, 178 m, NULL)) { 179 pfkeystat.in_nomem++; 180 m_freem(m); 181 error = ENOBUFS; 182 } else 183 error = 0; 184 sorwakeup(rp->rcb_socket); 185 return error; 186 } 187 188 /* XXX this interface should be obsoleted. */ 189 int 190 key_sendup(so, msg, len, target) 191 struct socket *so; 192 struct sadb_msg *msg; 193 u_int len; 194 int target; /*target of the resulting message*/ 195 { 196 struct mbuf *m, *n, *mprev; 197 int tlen; 198 199 /* sanity check */ 200 if (so == 0 || msg == 0) 201 panic("key_sendup: NULL pointer was passed.\n"); 202 203 KEYDEBUG(KEYDEBUG_KEY_DUMP, 204 printf("key_sendup: \n"); 205 kdebug_sadb(msg)); 206 207 /* 208 * we increment statistics here, just in case we have ENOBUFS 209 * in this function. 210 */ 211 pfkeystat.in_total++; 212 pfkeystat.in_bytes += len; 213 pfkeystat.in_msgtype[msg->sadb_msg_type]++; 214 215 /* 216 * Get mbuf chain whenever possible (not clusters), 217 * to save socket buffer. We'll be generating many SADB_ACQUIRE 218 * messages to listening key sockets. If we simply allocate clusters, 219 * sbappendaddr() will raise ENOBUFS due to too little sbspace(). 220 * sbspace() computes # of actual data bytes AND mbuf region. 221 * 222 * TODO: SADB_ACQUIRE filters should be implemented. 223 */ 224 tlen = len; 225 m = mprev = NULL; 226 while (tlen > 0) { 227 if (tlen == len) { 228 MGETHDR(n, M_DONTWAIT, MT_DATA); 229 n->m_len = MHLEN; 230 } else { 231 MGET(n, M_DONTWAIT, MT_DATA); 232 n->m_len = MLEN; 233 } 234 if (!n) { 235 pfkeystat.in_nomem++; 236 return ENOBUFS; 237 } 238 if (tlen >= MCLBYTES) { /*XXX better threshold? */ 239 MCLGET(n, M_DONTWAIT); 240 if ((n->m_flags & M_EXT) == 0) { 241 m_free(n); 242 m_freem(m); 243 pfkeystat.in_nomem++; 244 return ENOBUFS; 245 } 246 n->m_len = MCLBYTES; 247 } 248 249 if (tlen < n->m_len) 250 n->m_len = tlen; 251 n->m_next = NULL; 252 if (m == NULL) 253 m = mprev = n; 254 else { 255 mprev->m_next = n; 256 mprev = n; 257 } 258 tlen -= n->m_len; 259 n = NULL; 260 } 261 m->m_pkthdr.len = len; 262 m->m_pkthdr.rcvif = NULL; 263 m_copyback(m, 0, len, (caddr_t)msg); 264 265 /* avoid duplicated statistics */ 266 pfkeystat.in_total--; 267 pfkeystat.in_bytes -= len; 268 pfkeystat.in_msgtype[msg->sadb_msg_type]--; 269 270 return key_sendup_mbuf(so, m, target); 271 } 272 273 /* so can be NULL if target != KEY_SENDUP_ONE */ 274 int 275 key_sendup_mbuf(so, m, target) 276 struct socket *so; 277 struct mbuf *m; 278 int target; 279 { 280 struct mbuf *n; 281 struct keycb *kp; 282 int sendup; 283 struct rawcb *rp; 284 int error = 0; 285 286 if (m == NULL) 287 panic("key_sendup_mbuf: NULL pointer was passed.\n"); 288 if (so == NULL && target == KEY_SENDUP_ONE) 289 panic("key_sendup_mbuf: NULL pointer was passed.\n"); 290 291 pfkeystat.in_total++; 292 pfkeystat.in_bytes += m->m_pkthdr.len; 293 if (m->m_len < sizeof(struct sadb_msg)) { 294 #if 1 295 m = m_pullup(m, sizeof(struct sadb_msg)); 296 if (m == NULL) { 297 pfkeystat.in_nomem++; 298 return ENOBUFS; 299 } 300 #else 301 /* don't bother pulling it up just for stats */ 302 #endif 303 } 304 if (m->m_len >= sizeof(struct sadb_msg)) { 305 struct sadb_msg *msg; 306 msg = mtod(m, struct sadb_msg *); 307 pfkeystat.in_msgtype[msg->sadb_msg_type]++; 308 } 309 310 LIST_FOREACH(rp, &rawcb_list, rcb_list) 311 { 312 if (rp->rcb_proto.sp_family != PF_KEY) 313 continue; 314 if (rp->rcb_proto.sp_protocol 315 && rp->rcb_proto.sp_protocol != PF_KEY_V2) { 316 continue; 317 } 318 319 kp = (struct keycb *)rp; 320 321 /* 322 * If you are in promiscuous mode, and when you get broadcasted 323 * reply, you'll get two PF_KEY messages. 324 * (based on pf_key@inner.net message on 14 Oct 1998) 325 */ 326 if (((struct keycb *)rp)->kp_promisc) { 327 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { 328 (void)key_sendup0(rp, n, 1); 329 n = NULL; 330 } 331 } 332 333 /* the exact target will be processed later */ 334 if (so && sotorawcb(so) == rp) 335 continue; 336 337 sendup = 0; 338 switch (target) { 339 case KEY_SENDUP_ONE: 340 /* the statement has no effect */ 341 if (so && sotorawcb(so) == rp) 342 sendup++; 343 break; 344 case KEY_SENDUP_ALL: 345 sendup++; 346 break; 347 case KEY_SENDUP_REGISTERED: 348 if (kp->kp_registered) 349 sendup++; 350 break; 351 } 352 pfkeystat.in_msgtarget[target]++; 353 354 if (!sendup) 355 continue; 356 357 if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) { 358 m_freem(m); 359 pfkeystat.in_nomem++; 360 return ENOBUFS; 361 } 362 363 if ((error = key_sendup0(rp, n, 0)) != 0) { 364 m_freem(m); 365 return error; 366 } 367 368 n = NULL; 369 } 370 371 if (so) { 372 error = key_sendup0(sotorawcb(so), m, 0); 373 m = NULL; 374 } else { 375 error = 0; 376 m_freem(m); 377 } 378 return error; 379 } 380 381 #ifdef __FreeBSD__ 382 383 /* 384 * key_abort() 385 * derived from net/rtsock.c:rts_abort() 386 */ 387 static int 388 key_abort(struct socket *so) 389 { 390 int s, error; 391 s = splnet(); /* FreeBSD */ 392 error = raw_usrreqs.pru_abort(so); 393 splx(s); 394 return error; 395 } 396 397 /* 398 * key_attach() 399 * derived from net/rtsock.c:rts_attach() 400 */ 401 static int 402 key_attach(struct socket *so, int proto, struct proc *td) 403 { 404 struct keycb *kp; 405 int s, error; 406 407 if (sotorawcb(so) != 0) 408 return EISCONN; /* XXX panic? */ 409 kp = (struct keycb *)malloc(sizeof *kp, M_PCB, M_WAITOK|M_ZERO); /* XXX */ 410 if (kp == 0) 411 return ENOBUFS; 412 413 /* 414 * The spl[soft]net() is necessary to block protocols from sending 415 * error notifications (like RTM_REDIRECT or RTM_LOSING) while 416 * this PCB is extant but incompletely initialized. 417 * Probably we should try to do more of this work beforehand and 418 * eliminate the spl. 419 */ 420 s = splnet(); /* FreeBSD */ 421 so->so_pcb = (caddr_t)kp; 422 error = raw_usrreqs.pru_attach(so, proto, td); 423 kp = (struct keycb *)sotorawcb(so); 424 if (error) { 425 free(kp, M_PCB); 426 so->so_pcb = (caddr_t) 0; 427 splx(s); 428 return error; 429 } 430 431 kp->kp_promisc = kp->kp_registered = 0; 432 433 if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */ 434 key_cb.key_count++; 435 key_cb.any_count++; 436 kp->kp_raw.rcb_laddr = &key_src; 437 kp->kp_raw.rcb_faddr = &key_dst; 438 soisconnected(so); 439 so->so_options |= SO_USELOOPBACK; 440 441 splx(s); 442 return 0; 443 } 444 445 /* 446 * key_bind() 447 * derived from net/rtsock.c:rts_bind() 448 */ 449 static int 450 key_bind(struct socket *so, struct sockaddr *nam, struct proc *td) 451 { 452 int s, error; 453 s = splnet(); /* FreeBSD */ 454 error = raw_usrreqs.pru_bind(so, nam, td); /* xxx just EINVAL */ 455 splx(s); 456 return error; 457 } 458 459 /* 460 * key_connect() 461 * derived from net/rtsock.c:rts_connect() 462 */ 463 static int 464 key_connect(struct socket *so, struct sockaddr *nam, struct proc *td) 465 { 466 int s, error; 467 s = splnet(); /* FreeBSD */ 468 error = raw_usrreqs.pru_connect(so, nam, td); /* XXX just EINVAL */ 469 splx(s); 470 return error; 471 } 472 473 /* 474 * key_detach() 475 * derived from net/rtsock.c:rts_detach() 476 */ 477 static int 478 key_detach(struct socket *so) 479 { 480 struct keycb *kp = (struct keycb *)sotorawcb(so); 481 int s, error; 482 483 s = splnet(); /* FreeBSD */ 484 if (kp != 0) { 485 if (kp->kp_raw.rcb_proto.sp_protocol 486 == PF_KEY) /* XXX: AF_KEY */ 487 key_cb.key_count--; 488 key_cb.any_count--; 489 490 key_freereg(so); 491 } 492 error = raw_usrreqs.pru_detach(so); 493 splx(s); 494 return error; 495 } 496 497 /* 498 * key_disconnect() 499 * derived from net/rtsock.c:key_disconnect() 500 */ 501 static int 502 key_disconnect(struct socket *so) 503 { 504 int s, error; 505 s = splnet(); /* FreeBSD */ 506 error = raw_usrreqs.pru_disconnect(so); 507 splx(s); 508 return error; 509 } 510 511 /* 512 * key_peeraddr() 513 * derived from net/rtsock.c:rts_peeraddr() 514 */ 515 static int 516 key_peeraddr(struct socket *so, struct sockaddr **nam) 517 { 518 int s, error; 519 s = splnet(); /* FreeBSD */ 520 error = raw_usrreqs.pru_peeraddr(so, nam); 521 splx(s); 522 return error; 523 } 524 525 /* 526 * key_send() 527 * derived from net/rtsock.c:rts_send() 528 */ 529 static int 530 key_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, 531 struct mbuf *control, struct proc *td) 532 { 533 int s, error; 534 s = splnet(); /* FreeBSD */ 535 error = raw_usrreqs.pru_send(so, flags, m, nam, control, td); 536 splx(s); 537 return error; 538 } 539 540 /* 541 * key_shutdown() 542 * derived from net/rtsock.c:rts_shutdown() 543 */ 544 static int 545 key_shutdown(struct socket *so) 546 { 547 int s, error; 548 s = splnet(); /* FreeBSD */ 549 error = raw_usrreqs.pru_shutdown(so); 550 splx(s); 551 return error; 552 } 553 554 /* 555 * key_sockaddr() 556 * derived from net/rtsock.c:rts_sockaddr() 557 */ 558 static int 559 key_sockaddr(struct socket *so, struct sockaddr **nam) 560 { 561 int s, error; 562 s = splnet(); /* FreeBSD */ 563 error = raw_usrreqs.pru_sockaddr(so, nam); 564 splx(s); 565 return error; 566 } 567 #else /*!__FreeBSD__ -- traditional proto_usrreq() switch */ 568 569 /* 570 * key_usrreq() 571 * derived from net/rtsock.c:route_usrreq() 572 */ 573 int 574 key_usrreq(so, req, m, nam, control, p) 575 struct socket *so; 576 int req; 577 struct mbuf *m, *nam, *control; 578 struct proc *p; 579 { 580 int error = 0; 581 struct keycb *kp = (struct keycb *)sotorawcb(so); 582 int s; 583 584 s = splsoftnet(); 585 if (req == PRU_ATTACH) { 586 kp = (struct keycb *)malloc(sizeof(*kp), M_PCB, M_WAITOK); 587 so->so_pcb = (caddr_t)kp; 588 if (so->so_pcb) 589 bzero(so->so_pcb, sizeof(*kp)); 590 } 591 if (req == PRU_DETACH && kp) { 592 int af = kp->kp_raw.rcb_proto.sp_protocol; 593 if (af == PF_KEY) /* XXX: AF_KEY */ 594 key_cb.key_count--; 595 key_cb.any_count--; 596 597 key_freereg(so); 598 } 599 600 error = raw_usrreq(so, req, m, nam, control, p); 601 m = control = NULL; /* reclaimed in raw_usrreq */ 602 kp = (struct keycb *)sotorawcb(so); 603 if (req == PRU_ATTACH && kp) { 604 int af = kp->kp_raw.rcb_proto.sp_protocol; 605 if (error) { 606 pfkeystat.sockerr++; 607 free((caddr_t)kp, M_PCB); 608 so->so_pcb = (caddr_t) 0; 609 splx(s); 610 return (error); 611 } 612 613 kp->kp_promisc = kp->kp_registered = 0; 614 615 if (af == PF_KEY) /* XXX: AF_KEY */ 616 key_cb.key_count++; 617 key_cb.any_count++; 618 kp->kp_raw.rcb_laddr = &key_src; 619 kp->kp_raw.rcb_faddr = &key_dst; 620 soisconnected(so); 621 so->so_options |= SO_USELOOPBACK; 622 } 623 splx(s); 624 return (error); 625 } 626 #endif /*!__FreeBSD__*/ 627 628 /* sysctl */ 629 #ifdef SYSCTL_NODE 630 SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family"); 631 #endif /* SYSCTL_NODE */ 632 633 /* 634 * Definitions of protocols supported in the KEY domain. 635 */ 636 637 /* This extern declaration is all that's common... */ 638 extern struct domain keydomain; 639 640 #ifdef __FreeBSD__ 641 struct pr_usrreqs key_usrreqs = { 642 key_abort, pru_accept_notsupp, key_attach, key_bind, 643 key_connect, 644 pru_connect2_notsupp, pru_control_notsupp, key_detach, 645 key_disconnect, pru_listen_notsupp, key_peeraddr, 646 pru_rcvd_notsupp, 647 pru_rcvoob_notsupp, key_send, pru_sense_null, key_shutdown, 648 key_sockaddr, sosend, soreceive, sopoll 649 }; 650 651 struct protosw keysw[] = { 652 { SOCK_RAW, &keydomain, PF_KEY_V2, PR_ATOMIC|PR_ADDR, 653 0, (pr_output_t *)key_output, raw_ctlinput, 0, 654 0, 655 raw_init, 0, 0, 0, 656 &key_usrreqs 657 } 658 }; 659 660 static void 661 key_init0(void) 662 { 663 bzero((caddr_t)&key_cb, sizeof(key_cb)); 664 key_init(); 665 } 666 667 struct domain keydomain = 668 { PF_KEY, "key", key_init0, 0, 0, 669 keysw, &keysw[sizeof(keysw)/sizeof(keysw[0])] }; 670 671 DOMAIN_SET(key); 672 673 #else /* !__FreeBSD__ */ 674 675 676 struct protosw keysw[] = { 677 { SOCK_RAW, &keydomain, PF_KEY_V2, PR_ATOMIC|PR_ADDR, 678 0, key_output, raw_ctlinput, 0, 679 key_usrreq, 680 raw_init, 0, 0, 0, 681 NULL, 682 } 683 }; 684 685 struct domain keydomain = 686 { PF_KEY, "key", key_init, 0, 0, 687 keysw, &keysw[sizeof(keysw)/sizeof(keysw[0])] }; 688 689 #endif 690