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