1 /* 2 * Copyright (c) 1982, 1986, 1989, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * From: @(#)uipc_usrreq.c 8.3 (Berkeley) 1/4/94 30 */ 31 32 #include <sys/cdefs.h> 33 __FBSDID("$FreeBSD$"); 34 35 #include "opt_mac.h" 36 37 #include <sys/param.h> 38 #include <sys/domain.h> 39 #include <sys/fcntl.h> 40 #include <sys/malloc.h> /* XXX must be before <sys/file.h> */ 41 #include <sys/file.h> 42 #include <sys/filedesc.h> 43 #include <sys/jail.h> 44 #include <sys/kernel.h> 45 #include <sys/lock.h> 46 #include <sys/mac.h> 47 #include <sys/mbuf.h> 48 #include <sys/mutex.h> 49 #include <sys/namei.h> 50 #include <sys/proc.h> 51 #include <sys/protosw.h> 52 #include <sys/resourcevar.h> 53 #include <sys/socket.h> 54 #include <sys/socketvar.h> 55 #include <sys/signalvar.h> 56 #include <sys/stat.h> 57 #include <sys/sx.h> 58 #include <sys/sysctl.h> 59 #include <sys/systm.h> 60 #include <sys/un.h> 61 #include <sys/unpcb.h> 62 #include <sys/vnode.h> 63 64 #include <vm/uma.h> 65 66 static uma_zone_t unp_zone; 67 static unp_gen_t unp_gencnt; 68 static u_int unp_count; 69 70 static struct unp_head unp_shead, unp_dhead; 71 72 /* 73 * Unix communications domain. 74 * 75 * TODO: 76 * SEQPACKET, RDM 77 * rethink name space problems 78 * need a proper out-of-band 79 * lock pushdown 80 */ 81 static struct sockaddr sun_noname = { sizeof(sun_noname), AF_LOCAL }; 82 static ino_t unp_ino; /* prototype for fake inode numbers */ 83 84 static int unp_attach(struct socket *); 85 static void unp_detach(struct unpcb *); 86 static int unp_bind(struct unpcb *,struct sockaddr *, struct thread *); 87 static int unp_connect(struct socket *,struct sockaddr *, struct thread *); 88 static int unp_connect2(struct socket *so, struct socket *so2); 89 static void unp_disconnect(struct unpcb *); 90 static void unp_shutdown(struct unpcb *); 91 static void unp_drop(struct unpcb *, int); 92 static void unp_gc(void); 93 static void unp_scan(struct mbuf *, void (*)(struct file *)); 94 static void unp_mark(struct file *); 95 static void unp_discard(struct file *); 96 static void unp_freerights(struct file **, int); 97 static int unp_internalize(struct mbuf **, struct thread *); 98 static int unp_listen(struct unpcb *, struct thread *); 99 100 static int 101 uipc_abort(struct socket *so) 102 { 103 struct unpcb *unp = sotounpcb(so); 104 105 if (unp == NULL) 106 return (EINVAL); 107 unp_drop(unp, ECONNABORTED); 108 unp_detach(unp); 109 sotryfree(so); 110 return (0); 111 } 112 113 static int 114 uipc_accept(struct socket *so, struct sockaddr **nam) 115 { 116 struct unpcb *unp = sotounpcb(so); 117 118 if (unp == NULL) 119 return (EINVAL); 120 121 /* 122 * Pass back name of connected socket, 123 * if it was bound and we are still connected 124 * (our peer may have closed already!). 125 */ 126 if (unp->unp_conn != NULL && unp->unp_conn->unp_addr != NULL) { 127 *nam = sodupsockaddr( 128 (struct sockaddr *)unp->unp_conn->unp_addr, M_WAITOK); 129 } else { 130 *nam = sodupsockaddr((struct sockaddr *)&sun_noname, 131 M_WAITOK); 132 } 133 return (0); 134 } 135 136 static int 137 uipc_attach(struct socket *so, int proto, struct thread *td) 138 { 139 struct unpcb *unp = sotounpcb(so); 140 141 if (unp != NULL) 142 return (EISCONN); 143 return (unp_attach(so)); 144 } 145 146 static int 147 uipc_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 148 { 149 struct unpcb *unp = sotounpcb(so); 150 151 if (unp == NULL) 152 return (EINVAL); 153 154 return (unp_bind(unp, nam, td)); 155 } 156 157 static int 158 uipc_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 159 { 160 struct unpcb *unp = sotounpcb(so); 161 162 if (unp == NULL) 163 return (EINVAL); 164 return (unp_connect(so, nam, curthread)); 165 } 166 167 int 168 uipc_connect2(struct socket *so1, struct socket *so2) 169 { 170 struct unpcb *unp = sotounpcb(so1); 171 172 if (unp == NULL) 173 return (EINVAL); 174 175 return (unp_connect2(so1, so2)); 176 } 177 178 /* control is EOPNOTSUPP */ 179 180 static int 181 uipc_detach(struct socket *so) 182 { 183 struct unpcb *unp = sotounpcb(so); 184 185 if (unp == NULL) 186 return (EINVAL); 187 188 unp_detach(unp); 189 return (0); 190 } 191 192 static int 193 uipc_disconnect(struct socket *so) 194 { 195 struct unpcb *unp = sotounpcb(so); 196 197 if (unp == NULL) 198 return (EINVAL); 199 unp_disconnect(unp); 200 return (0); 201 } 202 203 static int 204 uipc_listen(struct socket *so, struct thread *td) 205 { 206 struct unpcb *unp = sotounpcb(so); 207 208 if (unp == NULL || unp->unp_vnode == NULL) 209 return (EINVAL); 210 return (unp_listen(unp, td)); 211 } 212 213 static int 214 uipc_peeraddr(struct socket *so, struct sockaddr **nam) 215 { 216 struct unpcb *unp = sotounpcb(so); 217 218 if (unp == NULL) 219 return (EINVAL); 220 if (unp->unp_conn != NULL && unp->unp_conn->unp_addr != NULL) 221 *nam = sodupsockaddr( 222 (struct sockaddr *)unp->unp_conn->unp_addr, M_WAITOK); 223 else { 224 /* 225 * XXX: It seems that this test always fails even when 226 * connection is established. So, this else clause is 227 * added as workaround to return PF_LOCAL sockaddr. 228 */ 229 *nam = sodupsockaddr((struct sockaddr *)&sun_noname, 230 M_WAITOK); 231 } 232 return (0); 233 } 234 235 static int 236 uipc_rcvd(struct socket *so, int flags) 237 { 238 struct unpcb *unp = sotounpcb(so); 239 struct socket *so2; 240 u_long newhiwat; 241 242 if (unp == NULL) 243 return (EINVAL); 244 switch (so->so_type) { 245 case SOCK_DGRAM: 246 panic("uipc_rcvd DGRAM?"); 247 /*NOTREACHED*/ 248 249 case SOCK_STREAM: 250 if (unp->unp_conn == NULL) 251 break; 252 so2 = unp->unp_conn->unp_socket; 253 /* 254 * Adjust backpressure on sender 255 * and wakeup any waiting to write. 256 */ 257 so2->so_snd.sb_mbmax += unp->unp_mbcnt - so->so_rcv.sb_mbcnt; 258 unp->unp_mbcnt = so->so_rcv.sb_mbcnt; 259 newhiwat = so2->so_snd.sb_hiwat + unp->unp_cc - 260 so->so_rcv.sb_cc; 261 (void)chgsbsize(so2->so_cred->cr_uidinfo, &so2->so_snd.sb_hiwat, 262 newhiwat, RLIM_INFINITY); 263 unp->unp_cc = so->so_rcv.sb_cc; 264 sowwakeup(so2); 265 break; 266 267 default: 268 panic("uipc_rcvd unknown socktype"); 269 } 270 return (0); 271 } 272 273 /* pru_rcvoob is EOPNOTSUPP */ 274 275 static int 276 uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, 277 struct mbuf *control, struct thread *td) 278 { 279 int error = 0; 280 struct unpcb *unp = sotounpcb(so); 281 struct socket *so2; 282 u_long newhiwat; 283 284 if (unp == NULL) { 285 error = EINVAL; 286 goto release; 287 } 288 if (flags & PRUS_OOB) { 289 error = EOPNOTSUPP; 290 goto release; 291 } 292 293 if (control != NULL && (error = unp_internalize(&control, td))) 294 goto release; 295 296 switch (so->so_type) { 297 case SOCK_DGRAM: 298 { 299 struct sockaddr *from; 300 301 if (nam != NULL) { 302 if (unp->unp_conn != NULL) { 303 error = EISCONN; 304 break; 305 } 306 error = unp_connect(so, nam, td); 307 if (error) 308 break; 309 } else { 310 if (unp->unp_conn == NULL) { 311 error = ENOTCONN; 312 break; 313 } 314 } 315 so2 = unp->unp_conn->unp_socket; 316 if (unp->unp_addr != NULL) 317 from = (struct sockaddr *)unp->unp_addr; 318 else 319 from = &sun_noname; 320 if (sbappendaddr(&so2->so_rcv, from, m, control)) { 321 sorwakeup(so2); 322 m = NULL; 323 control = NULL; 324 } else { 325 error = ENOBUFS; 326 } 327 if (nam != NULL) 328 unp_disconnect(unp); 329 break; 330 } 331 332 case SOCK_STREAM: 333 /* Connect if not connected yet. */ 334 /* 335 * Note: A better implementation would complain 336 * if not equal to the peer's address. 337 */ 338 if ((so->so_state & SS_ISCONNECTED) == 0) { 339 if (nam != NULL) { 340 error = unp_connect(so, nam, td); 341 if (error) 342 break; /* XXX */ 343 } else { 344 error = ENOTCONN; 345 break; 346 } 347 } 348 349 if (so->so_state & SS_CANTSENDMORE) { 350 error = EPIPE; 351 break; 352 } 353 if (unp->unp_conn == NULL) 354 panic("uipc_send connected but no connection?"); 355 so2 = unp->unp_conn->unp_socket; 356 /* 357 * Send to paired receive port, and then reduce 358 * send buffer hiwater marks to maintain backpressure. 359 * Wake up readers. 360 */ 361 if (control != NULL) { 362 if (sbappendcontrol(&so2->so_rcv, m, control)) 363 control = NULL; 364 } else { 365 sbappend(&so2->so_rcv, m); 366 } 367 so->so_snd.sb_mbmax -= 368 so2->so_rcv.sb_mbcnt - unp->unp_conn->unp_mbcnt; 369 unp->unp_conn->unp_mbcnt = so2->so_rcv.sb_mbcnt; 370 newhiwat = so->so_snd.sb_hiwat - 371 (so2->so_rcv.sb_cc - unp->unp_conn->unp_cc); 372 (void)chgsbsize(so->so_cred->cr_uidinfo, &so->so_snd.sb_hiwat, 373 newhiwat, RLIM_INFINITY); 374 unp->unp_conn->unp_cc = so2->so_rcv.sb_cc; 375 sorwakeup(so2); 376 m = NULL; 377 break; 378 379 default: 380 panic("uipc_send unknown socktype"); 381 } 382 383 /* 384 * SEND_EOF is equivalent to a SEND followed by 385 * a SHUTDOWN. 386 */ 387 if (flags & PRUS_EOF) { 388 socantsendmore(so); 389 unp_shutdown(unp); 390 } 391 392 if (control != NULL && error != 0) 393 unp_dispose(control); 394 395 release: 396 if (control != NULL) 397 m_freem(control); 398 if (m != NULL) 399 m_freem(m); 400 return (error); 401 } 402 403 static int 404 uipc_sense(struct socket *so, struct stat *sb) 405 { 406 struct unpcb *unp = sotounpcb(so); 407 struct socket *so2; 408 409 if (unp == NULL) 410 return (EINVAL); 411 sb->st_blksize = so->so_snd.sb_hiwat; 412 if (so->so_type == SOCK_STREAM && unp->unp_conn != NULL) { 413 so2 = unp->unp_conn->unp_socket; 414 sb->st_blksize += so2->so_rcv.sb_cc; 415 } 416 sb->st_dev = NOUDEV; 417 if (unp->unp_ino == 0) 418 unp->unp_ino = (++unp_ino == 0) ? ++unp_ino : unp_ino; 419 sb->st_ino = unp->unp_ino; 420 return (0); 421 } 422 423 static int 424 uipc_shutdown(struct socket *so) 425 { 426 struct unpcb *unp = sotounpcb(so); 427 428 if (unp == NULL) 429 return (EINVAL); 430 socantsendmore(so); 431 unp_shutdown(unp); 432 return (0); 433 } 434 435 static int 436 uipc_sockaddr(struct socket *so, struct sockaddr **nam) 437 { 438 struct unpcb *unp = sotounpcb(so); 439 440 if (unp == NULL) 441 return (EINVAL); 442 if (unp->unp_addr != NULL) 443 *nam = sodupsockaddr((struct sockaddr *)unp->unp_addr, 444 M_WAITOK); 445 else 446 *nam = sodupsockaddr((struct sockaddr *)&sun_noname, 447 M_WAITOK); 448 return (0); 449 } 450 451 struct pr_usrreqs uipc_usrreqs = { 452 uipc_abort, uipc_accept, uipc_attach, uipc_bind, uipc_connect, 453 uipc_connect2, pru_control_notsupp, uipc_detach, uipc_disconnect, 454 uipc_listen, uipc_peeraddr, uipc_rcvd, pru_rcvoob_notsupp, 455 uipc_send, uipc_sense, uipc_shutdown, uipc_sockaddr, 456 sosend, soreceive, sopoll, pru_sosetlabel_null 457 }; 458 459 int 460 uipc_ctloutput(so, sopt) 461 struct socket *so; 462 struct sockopt *sopt; 463 { 464 struct unpcb *unp = sotounpcb(so); 465 int error; 466 467 switch (sopt->sopt_dir) { 468 case SOPT_GET: 469 switch (sopt->sopt_name) { 470 case LOCAL_PEERCRED: 471 if (unp->unp_flags & UNP_HAVEPC) 472 error = sooptcopyout(sopt, &unp->unp_peercred, 473 sizeof(unp->unp_peercred)); 474 else { 475 if (so->so_type == SOCK_STREAM) 476 error = ENOTCONN; 477 else 478 error = EINVAL; 479 } 480 break; 481 default: 482 error = EOPNOTSUPP; 483 break; 484 } 485 break; 486 case SOPT_SET: 487 default: 488 error = EOPNOTSUPP; 489 break; 490 } 491 return (error); 492 } 493 494 /* 495 * Both send and receive buffers are allocated PIPSIZ bytes of buffering 496 * for stream sockets, although the total for sender and receiver is 497 * actually only PIPSIZ. 498 * Datagram sockets really use the sendspace as the maximum datagram size, 499 * and don't really want to reserve the sendspace. Their recvspace should 500 * be large enough for at least one max-size datagram plus address. 501 */ 502 #ifndef PIPSIZ 503 #define PIPSIZ 8192 504 #endif 505 static u_long unpst_sendspace = PIPSIZ; 506 static u_long unpst_recvspace = PIPSIZ; 507 static u_long unpdg_sendspace = 2*1024; /* really max datagram size */ 508 static u_long unpdg_recvspace = 4*1024; 509 510 static int unp_rights; /* file descriptors in flight */ 511 512 SYSCTL_DECL(_net_local_stream); 513 SYSCTL_INT(_net_local_stream, OID_AUTO, sendspace, CTLFLAG_RW, 514 &unpst_sendspace, 0, ""); 515 SYSCTL_INT(_net_local_stream, OID_AUTO, recvspace, CTLFLAG_RW, 516 &unpst_recvspace, 0, ""); 517 SYSCTL_DECL(_net_local_dgram); 518 SYSCTL_INT(_net_local_dgram, OID_AUTO, maxdgram, CTLFLAG_RW, 519 &unpdg_sendspace, 0, ""); 520 SYSCTL_INT(_net_local_dgram, OID_AUTO, recvspace, CTLFLAG_RW, 521 &unpdg_recvspace, 0, ""); 522 SYSCTL_DECL(_net_local); 523 SYSCTL_INT(_net_local, OID_AUTO, inflight, CTLFLAG_RD, &unp_rights, 0, ""); 524 525 static int 526 unp_attach(so) 527 struct socket *so; 528 { 529 register struct unpcb *unp; 530 int error; 531 532 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 533 switch (so->so_type) { 534 535 case SOCK_STREAM: 536 error = soreserve(so, unpst_sendspace, unpst_recvspace); 537 break; 538 539 case SOCK_DGRAM: 540 error = soreserve(so, unpdg_sendspace, unpdg_recvspace); 541 break; 542 543 default: 544 panic("unp_attach"); 545 } 546 if (error) 547 return (error); 548 } 549 unp = uma_zalloc(unp_zone, M_WAITOK); 550 if (unp == NULL) 551 return (ENOBUFS); 552 bzero(unp, sizeof *unp); 553 unp->unp_gencnt = ++unp_gencnt; 554 unp_count++; 555 LIST_INIT(&unp->unp_refs); 556 unp->unp_socket = so; 557 LIST_INSERT_HEAD(so->so_type == SOCK_DGRAM ? &unp_dhead 558 : &unp_shead, unp, unp_link); 559 so->so_pcb = unp; 560 return (0); 561 } 562 563 static void 564 unp_detach(unp) 565 register struct unpcb *unp; 566 { 567 LIST_REMOVE(unp, unp_link); 568 unp->unp_gencnt = ++unp_gencnt; 569 --unp_count; 570 if (unp->unp_vnode != NULL) { 571 unp->unp_vnode->v_socket = NULL; 572 vrele(unp->unp_vnode); 573 unp->unp_vnode = NULL; 574 } 575 if (unp->unp_conn != NULL) 576 unp_disconnect(unp); 577 while (!LIST_EMPTY(&unp->unp_refs)) 578 unp_drop(LIST_FIRST(&unp->unp_refs), ECONNRESET); 579 soisdisconnected(unp->unp_socket); 580 unp->unp_socket->so_pcb = NULL; 581 if (unp_rights) { 582 /* 583 * Normally the receive buffer is flushed later, 584 * in sofree, but if our receive buffer holds references 585 * to descriptors that are now garbage, we will dispose 586 * of those descriptor references after the garbage collector 587 * gets them (resulting in a "panic: closef: count < 0"). 588 */ 589 sorflush(unp->unp_socket); 590 unp_gc(); 591 } 592 if (unp->unp_addr != NULL) 593 FREE(unp->unp_addr, M_SONAME); 594 uma_zfree(unp_zone, unp); 595 } 596 597 static int 598 unp_bind(unp, nam, td) 599 struct unpcb *unp; 600 struct sockaddr *nam; 601 struct thread *td; 602 { 603 struct sockaddr_un *soun = (struct sockaddr_un *)nam; 604 struct vnode *vp; 605 struct mount *mp; 606 struct vattr vattr; 607 int error, namelen; 608 struct nameidata nd; 609 char *buf; 610 611 if (unp->unp_vnode != NULL) 612 return (EINVAL); 613 614 namelen = soun->sun_len - offsetof(struct sockaddr_un, sun_path); 615 if (namelen <= 0) 616 return (EINVAL); 617 618 buf = malloc(namelen + 1, M_TEMP, M_WAITOK); 619 strlcpy(buf, soun->sun_path, namelen + 1); 620 621 restart: 622 NDINIT(&nd, CREATE, NOFOLLOW | LOCKPARENT | SAVENAME, UIO_SYSSPACE, 623 buf, td); 624 /* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */ 625 error = namei(&nd); 626 if (error) { 627 free(buf, M_TEMP); 628 return (error); 629 } 630 vp = nd.ni_vp; 631 if (vp != NULL || vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 632 NDFREE(&nd, NDF_ONLY_PNBUF); 633 if (nd.ni_dvp == vp) 634 vrele(nd.ni_dvp); 635 else 636 vput(nd.ni_dvp); 637 if (vp != NULL) { 638 vrele(vp); 639 free(buf, M_TEMP); 640 return (EADDRINUSE); 641 } 642 error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH); 643 if (error) { 644 free(buf, M_TEMP); 645 return (error); 646 } 647 goto restart; 648 } 649 VATTR_NULL(&vattr); 650 vattr.va_type = VSOCK; 651 vattr.va_mode = (ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask); 652 #ifdef MAC 653 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd, 654 &vattr); 655 #endif 656 if (error == 0) { 657 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 658 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 659 } 660 NDFREE(&nd, NDF_ONLY_PNBUF); 661 vput(nd.ni_dvp); 662 if (error) { 663 free(buf, M_TEMP); 664 return (error); 665 } 666 vp = nd.ni_vp; 667 vp->v_socket = unp->unp_socket; 668 unp->unp_vnode = vp; 669 unp->unp_addr = (struct sockaddr_un *)sodupsockaddr(nam, M_WAITOK); 670 VOP_UNLOCK(vp, 0, td); 671 vn_finished_write(mp); 672 free(buf, M_TEMP); 673 return (0); 674 } 675 676 static int 677 unp_connect(so, nam, td) 678 struct socket *so; 679 struct sockaddr *nam; 680 struct thread *td; 681 { 682 register struct sockaddr_un *soun = (struct sockaddr_un *)nam; 683 register struct vnode *vp; 684 register struct socket *so2, *so3; 685 struct unpcb *unp, *unp2, *unp3; 686 int error, len; 687 struct nameidata nd; 688 char buf[SOCK_MAXADDRLEN]; 689 690 len = nam->sa_len - offsetof(struct sockaddr_un, sun_path); 691 if (len <= 0) 692 return (EINVAL); 693 strlcpy(buf, soun->sun_path, len + 1); 694 695 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, buf, td); 696 error = namei(&nd); 697 if (error) 698 return (error); 699 vp = nd.ni_vp; 700 NDFREE(&nd, NDF_ONLY_PNBUF); 701 if (vp->v_type != VSOCK) { 702 error = ENOTSOCK; 703 goto bad; 704 } 705 error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td); 706 if (error) 707 goto bad; 708 so2 = vp->v_socket; 709 if (so2 == NULL) { 710 error = ECONNREFUSED; 711 goto bad; 712 } 713 if (so->so_type != so2->so_type) { 714 error = EPROTOTYPE; 715 goto bad; 716 } 717 if (so->so_proto->pr_flags & PR_CONNREQUIRED) { 718 if ((so2->so_options & SO_ACCEPTCONN) == 0 || 719 (so3 = sonewconn(so2, 0)) == NULL) { 720 error = ECONNREFUSED; 721 goto bad; 722 } 723 unp = sotounpcb(so); 724 unp2 = sotounpcb(so2); 725 unp3 = sotounpcb(so3); 726 if (unp2->unp_addr != NULL) 727 unp3->unp_addr = (struct sockaddr_un *) 728 sodupsockaddr((struct sockaddr *)unp2->unp_addr, 729 M_WAITOK); 730 731 /* 732 * unp_peercred management: 733 * 734 * The connecter's (client's) credentials are copied 735 * from its process structure at the time of connect() 736 * (which is now). 737 */ 738 cru2x(td->td_ucred, &unp3->unp_peercred); 739 unp3->unp_flags |= UNP_HAVEPC; 740 /* 741 * The receiver's (server's) credentials are copied 742 * from the unp_peercred member of socket on which the 743 * former called listen(); unp_listen() cached that 744 * process's credentials at that time so we can use 745 * them now. 746 */ 747 KASSERT(unp2->unp_flags & UNP_HAVEPCCACHED, 748 ("unp_connect: listener without cached peercred")); 749 memcpy(&unp->unp_peercred, &unp2->unp_peercred, 750 sizeof(unp->unp_peercred)); 751 unp->unp_flags |= UNP_HAVEPC; 752 #ifdef MAC 753 mac_set_socket_peer_from_socket(so, so3); 754 mac_set_socket_peer_from_socket(so3, so); 755 #endif 756 757 so2 = so3; 758 } 759 error = unp_connect2(so, so2); 760 bad: 761 vput(vp); 762 return (error); 763 } 764 765 static int 766 unp_connect2(so, so2) 767 register struct socket *so; 768 register struct socket *so2; 769 { 770 register struct unpcb *unp = sotounpcb(so); 771 register struct unpcb *unp2; 772 773 if (so2->so_type != so->so_type) 774 return (EPROTOTYPE); 775 unp2 = sotounpcb(so2); 776 unp->unp_conn = unp2; 777 switch (so->so_type) { 778 779 case SOCK_DGRAM: 780 LIST_INSERT_HEAD(&unp2->unp_refs, unp, unp_reflink); 781 soisconnected(so); 782 break; 783 784 case SOCK_STREAM: 785 unp2->unp_conn = unp; 786 soisconnected(so); 787 soisconnected(so2); 788 break; 789 790 default: 791 panic("unp_connect2"); 792 } 793 return (0); 794 } 795 796 static void 797 unp_disconnect(unp) 798 struct unpcb *unp; 799 { 800 register struct unpcb *unp2 = unp->unp_conn; 801 802 if (unp2 == NULL) 803 return; 804 unp->unp_conn = NULL; 805 switch (unp->unp_socket->so_type) { 806 807 case SOCK_DGRAM: 808 LIST_REMOVE(unp, unp_reflink); 809 unp->unp_socket->so_state &= ~SS_ISCONNECTED; 810 break; 811 812 case SOCK_STREAM: 813 soisdisconnected(unp->unp_socket); 814 unp2->unp_conn = NULL; 815 soisdisconnected(unp2->unp_socket); 816 break; 817 } 818 } 819 820 #ifdef notdef 821 void 822 unp_abort(unp) 823 struct unpcb *unp; 824 { 825 826 unp_detach(unp); 827 } 828 #endif 829 830 static int 831 unp_pcblist(SYSCTL_HANDLER_ARGS) 832 { 833 int error, i, n; 834 struct unpcb *unp, **unp_list; 835 unp_gen_t gencnt; 836 struct xunpgen *xug; 837 struct unp_head *head; 838 struct xunpcb *xu; 839 840 head = ((intptr_t)arg1 == SOCK_DGRAM ? &unp_dhead : &unp_shead); 841 842 /* 843 * The process of preparing the PCB list is too time-consuming and 844 * resource-intensive to repeat twice on every request. 845 */ 846 if (req->oldptr == NULL) { 847 n = unp_count; 848 req->oldidx = 2 * (sizeof *xug) 849 + (n + n/8) * sizeof(struct xunpcb); 850 return (0); 851 } 852 853 if (req->newptr != NULL) 854 return (EPERM); 855 856 /* 857 * OK, now we're committed to doing something. 858 */ 859 xug = malloc(sizeof(*xug), M_TEMP, M_WAITOK); 860 gencnt = unp_gencnt; 861 n = unp_count; 862 863 xug->xug_len = sizeof *xug; 864 xug->xug_count = n; 865 xug->xug_gen = gencnt; 866 xug->xug_sogen = so_gencnt; 867 error = SYSCTL_OUT(req, xug, sizeof *xug); 868 if (error) { 869 free(xug, M_TEMP); 870 return (error); 871 } 872 873 unp_list = malloc(n * sizeof *unp_list, M_TEMP, M_WAITOK); 874 875 for (unp = LIST_FIRST(head), i = 0; unp && i < n; 876 unp = LIST_NEXT(unp, unp_link)) { 877 if (unp->unp_gencnt <= gencnt) { 878 if (cr_cansee(req->td->td_ucred, 879 unp->unp_socket->so_cred)) 880 continue; 881 unp_list[i++] = unp; 882 } 883 } 884 n = i; /* in case we lost some during malloc */ 885 886 error = 0; 887 xu = malloc(sizeof(*xu), M_TEMP, M_WAITOK); 888 for (i = 0; i < n; i++) { 889 unp = unp_list[i]; 890 if (unp->unp_gencnt <= gencnt) { 891 xu->xu_len = sizeof *xu; 892 xu->xu_unpp = unp; 893 /* 894 * XXX - need more locking here to protect against 895 * connect/disconnect races for SMP. 896 */ 897 if (unp->unp_addr != NULL) 898 bcopy(unp->unp_addr, &xu->xu_addr, 899 unp->unp_addr->sun_len); 900 if (unp->unp_conn != NULL && 901 unp->unp_conn->unp_addr != NULL) 902 bcopy(unp->unp_conn->unp_addr, 903 &xu->xu_caddr, 904 unp->unp_conn->unp_addr->sun_len); 905 bcopy(unp, &xu->xu_unp, sizeof *unp); 906 sotoxsocket(unp->unp_socket, &xu->xu_socket); 907 error = SYSCTL_OUT(req, xu, sizeof *xu); 908 } 909 } 910 free(xu, M_TEMP); 911 if (!error) { 912 /* 913 * Give the user an updated idea of our state. 914 * If the generation differs from what we told 915 * her before, she knows that something happened 916 * while we were processing this request, and it 917 * might be necessary to retry. 918 */ 919 xug->xug_gen = unp_gencnt; 920 xug->xug_sogen = so_gencnt; 921 xug->xug_count = unp_count; 922 error = SYSCTL_OUT(req, xug, sizeof *xug); 923 } 924 free(unp_list, M_TEMP); 925 free(xug, M_TEMP); 926 return (error); 927 } 928 929 SYSCTL_PROC(_net_local_dgram, OID_AUTO, pcblist, CTLFLAG_RD, 930 (caddr_t)(long)SOCK_DGRAM, 0, unp_pcblist, "S,xunpcb", 931 "List of active local datagram sockets"); 932 SYSCTL_PROC(_net_local_stream, OID_AUTO, pcblist, CTLFLAG_RD, 933 (caddr_t)(long)SOCK_STREAM, 0, unp_pcblist, "S,xunpcb", 934 "List of active local stream sockets"); 935 936 static void 937 unp_shutdown(unp) 938 struct unpcb *unp; 939 { 940 struct socket *so; 941 942 if (unp->unp_socket->so_type == SOCK_STREAM && unp->unp_conn && 943 (so = unp->unp_conn->unp_socket)) 944 socantrcvmore(so); 945 } 946 947 static void 948 unp_drop(unp, errno) 949 struct unpcb *unp; 950 int errno; 951 { 952 struct socket *so = unp->unp_socket; 953 954 so->so_error = errno; 955 unp_disconnect(unp); 956 } 957 958 #ifdef notdef 959 void 960 unp_drain() 961 { 962 963 } 964 #endif 965 966 static void 967 unp_freerights(rp, fdcount) 968 struct file **rp; 969 int fdcount; 970 { 971 int i; 972 struct file *fp; 973 974 for (i = 0; i < fdcount; i++) { 975 fp = *rp; 976 /* 977 * zero the pointer before calling 978 * unp_discard since it may end up 979 * in unp_gc().. 980 */ 981 *rp++ = 0; 982 unp_discard(fp); 983 } 984 } 985 986 int 987 unp_externalize(control, controlp) 988 struct mbuf *control, **controlp; 989 { 990 struct thread *td = curthread; /* XXX */ 991 struct cmsghdr *cm = mtod(control, struct cmsghdr *); 992 int i; 993 int *fdp; 994 struct file **rp; 995 struct file *fp; 996 void *data; 997 socklen_t clen = control->m_len, datalen; 998 int error, newfds; 999 int f; 1000 u_int newlen; 1001 1002 error = 0; 1003 if (controlp != NULL) /* controlp == NULL => free control messages */ 1004 *controlp = NULL; 1005 1006 while (cm != NULL) { 1007 if (sizeof(*cm) > clen || cm->cmsg_len > clen) { 1008 error = EINVAL; 1009 break; 1010 } 1011 1012 data = CMSG_DATA(cm); 1013 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; 1014 1015 if (cm->cmsg_level == SOL_SOCKET 1016 && cm->cmsg_type == SCM_RIGHTS) { 1017 newfds = datalen / sizeof(struct file *); 1018 rp = data; 1019 1020 /* If we're not outputting the descriptors free them. */ 1021 if (error || controlp == NULL) { 1022 unp_freerights(rp, newfds); 1023 goto next; 1024 } 1025 FILEDESC_LOCK(td->td_proc->p_fd); 1026 /* if the new FD's will not fit free them. */ 1027 if (!fdavail(td, newfds)) { 1028 FILEDESC_UNLOCK(td->td_proc->p_fd); 1029 error = EMSGSIZE; 1030 unp_freerights(rp, newfds); 1031 goto next; 1032 } 1033 /* 1034 * now change each pointer to an fd in the global 1035 * table to an integer that is the index to the 1036 * local fd table entry that we set up to point 1037 * to the global one we are transferring. 1038 */ 1039 newlen = newfds * sizeof(int); 1040 *controlp = sbcreatecontrol(NULL, newlen, 1041 SCM_RIGHTS, SOL_SOCKET); 1042 if (*controlp == NULL) { 1043 FILEDESC_UNLOCK(td->td_proc->p_fd); 1044 error = E2BIG; 1045 unp_freerights(rp, newfds); 1046 goto next; 1047 } 1048 1049 fdp = (int *) 1050 CMSG_DATA(mtod(*controlp, struct cmsghdr *)); 1051 for (i = 0; i < newfds; i++) { 1052 if (fdalloc(td, 0, &f)) 1053 panic("unp_externalize fdalloc failed"); 1054 fp = *rp++; 1055 td->td_proc->p_fd->fd_ofiles[f] = fp; 1056 FILE_LOCK(fp); 1057 fp->f_msgcount--; 1058 FILE_UNLOCK(fp); 1059 unp_rights--; 1060 *fdp++ = f; 1061 } 1062 FILEDESC_UNLOCK(td->td_proc->p_fd); 1063 } else { /* We can just copy anything else across */ 1064 if (error || controlp == NULL) 1065 goto next; 1066 *controlp = sbcreatecontrol(NULL, datalen, 1067 cm->cmsg_type, cm->cmsg_level); 1068 if (*controlp == NULL) { 1069 error = ENOBUFS; 1070 goto next; 1071 } 1072 bcopy(data, 1073 CMSG_DATA(mtod(*controlp, struct cmsghdr *)), 1074 datalen); 1075 } 1076 1077 controlp = &(*controlp)->m_next; 1078 1079 next: 1080 if (CMSG_SPACE(datalen) < clen) { 1081 clen -= CMSG_SPACE(datalen); 1082 cm = (struct cmsghdr *) 1083 ((caddr_t)cm + CMSG_SPACE(datalen)); 1084 } else { 1085 clen = 0; 1086 cm = NULL; 1087 } 1088 } 1089 1090 m_freem(control); 1091 1092 return (error); 1093 } 1094 1095 void 1096 unp_init(void) 1097 { 1098 unp_zone = uma_zcreate("unpcb", sizeof(struct unpcb), NULL, NULL, 1099 NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); 1100 if (unp_zone == NULL) 1101 panic("unp_init"); 1102 uma_zone_set_max(unp_zone, nmbclusters); 1103 LIST_INIT(&unp_dhead); 1104 LIST_INIT(&unp_shead); 1105 } 1106 1107 static int 1108 unp_internalize(controlp, td) 1109 struct mbuf **controlp; 1110 struct thread *td; 1111 { 1112 struct mbuf *control = *controlp; 1113 struct proc *p = td->td_proc; 1114 struct filedesc *fdescp = p->p_fd; 1115 struct cmsghdr *cm = mtod(control, struct cmsghdr *); 1116 struct cmsgcred *cmcred; 1117 struct file **rp; 1118 struct file *fp; 1119 struct timeval *tv; 1120 int i, fd, *fdp; 1121 void *data; 1122 socklen_t clen = control->m_len, datalen; 1123 int error, oldfds; 1124 u_int newlen; 1125 1126 error = 0; 1127 *controlp = NULL; 1128 1129 while (cm != NULL) { 1130 if (sizeof(*cm) > clen || cm->cmsg_level != SOL_SOCKET 1131 || cm->cmsg_len > clen) { 1132 error = EINVAL; 1133 goto out; 1134 } 1135 1136 data = CMSG_DATA(cm); 1137 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; 1138 1139 switch (cm->cmsg_type) { 1140 /* 1141 * Fill in credential information. 1142 */ 1143 case SCM_CREDS: 1144 *controlp = sbcreatecontrol(NULL, sizeof(*cmcred), 1145 SCM_CREDS, SOL_SOCKET); 1146 if (*controlp == NULL) { 1147 error = ENOBUFS; 1148 goto out; 1149 } 1150 1151 cmcred = (struct cmsgcred *) 1152 CMSG_DATA(mtod(*controlp, struct cmsghdr *)); 1153 cmcred->cmcred_pid = p->p_pid; 1154 cmcred->cmcred_uid = td->td_ucred->cr_ruid; 1155 cmcred->cmcred_gid = td->td_ucred->cr_rgid; 1156 cmcred->cmcred_euid = td->td_ucred->cr_uid; 1157 cmcred->cmcred_ngroups = MIN(td->td_ucred->cr_ngroups, 1158 CMGROUP_MAX); 1159 for (i = 0; i < cmcred->cmcred_ngroups; i++) 1160 cmcred->cmcred_groups[i] = 1161 td->td_ucred->cr_groups[i]; 1162 break; 1163 1164 case SCM_RIGHTS: 1165 oldfds = datalen / sizeof (int); 1166 /* 1167 * check that all the FDs passed in refer to legal files 1168 * If not, reject the entire operation. 1169 */ 1170 fdp = data; 1171 FILEDESC_LOCK(fdescp); 1172 for (i = 0; i < oldfds; i++) { 1173 fd = *fdp++; 1174 if ((unsigned)fd >= fdescp->fd_nfiles || 1175 fdescp->fd_ofiles[fd] == NULL) { 1176 FILEDESC_UNLOCK(fdescp); 1177 error = EBADF; 1178 goto out; 1179 } 1180 fp = fdescp->fd_ofiles[fd]; 1181 if (!(fp->f_ops->fo_flags & DFLAG_PASSABLE)) { 1182 FILEDESC_UNLOCK(fdescp); 1183 error = EOPNOTSUPP; 1184 goto out; 1185 } 1186 1187 } 1188 /* 1189 * Now replace the integer FDs with pointers to 1190 * the associated global file table entry.. 1191 */ 1192 newlen = oldfds * sizeof(struct file *); 1193 *controlp = sbcreatecontrol(NULL, newlen, 1194 SCM_RIGHTS, SOL_SOCKET); 1195 if (*controlp == NULL) { 1196 FILEDESC_UNLOCK(fdescp); 1197 error = E2BIG; 1198 goto out; 1199 } 1200 1201 fdp = data; 1202 rp = (struct file **) 1203 CMSG_DATA(mtod(*controlp, struct cmsghdr *)); 1204 for (i = 0; i < oldfds; i++) { 1205 fp = fdescp->fd_ofiles[*fdp++]; 1206 *rp++ = fp; 1207 FILE_LOCK(fp); 1208 fp->f_count++; 1209 fp->f_msgcount++; 1210 FILE_UNLOCK(fp); 1211 unp_rights++; 1212 } 1213 FILEDESC_UNLOCK(fdescp); 1214 break; 1215 1216 case SCM_TIMESTAMP: 1217 *controlp = sbcreatecontrol(NULL, sizeof(*tv), 1218 SCM_TIMESTAMP, SOL_SOCKET); 1219 if (*controlp == NULL) { 1220 error = ENOBUFS; 1221 goto out; 1222 } 1223 tv = (struct timeval *) 1224 CMSG_DATA(mtod(*controlp, struct cmsghdr *)); 1225 microtime(tv); 1226 break; 1227 1228 default: 1229 error = EINVAL; 1230 goto out; 1231 } 1232 1233 controlp = &(*controlp)->m_next; 1234 1235 if (CMSG_SPACE(datalen) < clen) { 1236 clen -= CMSG_SPACE(datalen); 1237 cm = (struct cmsghdr *) 1238 ((caddr_t)cm + CMSG_SPACE(datalen)); 1239 } else { 1240 clen = 0; 1241 cm = NULL; 1242 } 1243 } 1244 1245 out: 1246 m_freem(control); 1247 1248 return (error); 1249 } 1250 1251 static int unp_defer, unp_gcing; 1252 1253 static void 1254 unp_gc() 1255 { 1256 register struct file *fp, *nextfp; 1257 register struct socket *so; 1258 struct file **extra_ref, **fpp; 1259 int nunref, i; 1260 1261 if (unp_gcing) 1262 return; 1263 unp_gcing = 1; 1264 unp_defer = 0; 1265 /* 1266 * before going through all this, set all FDs to 1267 * be NOT defered and NOT externally accessible 1268 */ 1269 sx_slock(&filelist_lock); 1270 LIST_FOREACH(fp, &filehead, f_list) 1271 fp->f_gcflag &= ~(FMARK|FDEFER); 1272 do { 1273 LIST_FOREACH(fp, &filehead, f_list) { 1274 FILE_LOCK(fp); 1275 /* 1276 * If the file is not open, skip it 1277 */ 1278 if (fp->f_count == 0) { 1279 FILE_UNLOCK(fp); 1280 continue; 1281 } 1282 /* 1283 * If we already marked it as 'defer' in a 1284 * previous pass, then try process it this time 1285 * and un-mark it 1286 */ 1287 if (fp->f_gcflag & FDEFER) { 1288 fp->f_gcflag &= ~FDEFER; 1289 unp_defer--; 1290 } else { 1291 /* 1292 * if it's not defered, then check if it's 1293 * already marked.. if so skip it 1294 */ 1295 if (fp->f_gcflag & FMARK) { 1296 FILE_UNLOCK(fp); 1297 continue; 1298 } 1299 /* 1300 * If all references are from messages 1301 * in transit, then skip it. it's not 1302 * externally accessible. 1303 */ 1304 if (fp->f_count == fp->f_msgcount) { 1305 FILE_UNLOCK(fp); 1306 continue; 1307 } 1308 /* 1309 * If it got this far then it must be 1310 * externally accessible. 1311 */ 1312 fp->f_gcflag |= FMARK; 1313 } 1314 /* 1315 * either it was defered, or it is externally 1316 * accessible and not already marked so. 1317 * Now check if it is possibly one of OUR sockets. 1318 */ 1319 if (fp->f_type != DTYPE_SOCKET || 1320 (so = fp->f_data) == NULL) { 1321 FILE_UNLOCK(fp); 1322 continue; 1323 } 1324 FILE_UNLOCK(fp); 1325 if (so->so_proto->pr_domain != &localdomain || 1326 (so->so_proto->pr_flags&PR_RIGHTS) == 0) 1327 continue; 1328 #ifdef notdef 1329 if (so->so_rcv.sb_flags & SB_LOCK) { 1330 /* 1331 * This is problematical; it's not clear 1332 * we need to wait for the sockbuf to be 1333 * unlocked (on a uniprocessor, at least), 1334 * and it's also not clear what to do 1335 * if sbwait returns an error due to receipt 1336 * of a signal. If sbwait does return 1337 * an error, we'll go into an infinite 1338 * loop. Delete all of this for now. 1339 */ 1340 (void) sbwait(&so->so_rcv); 1341 goto restart; 1342 } 1343 #endif 1344 /* 1345 * So, Ok, it's one of our sockets and it IS externally 1346 * accessible (or was defered). Now we look 1347 * to see if we hold any file descriptors in its 1348 * message buffers. Follow those links and mark them 1349 * as accessible too. 1350 */ 1351 unp_scan(so->so_rcv.sb_mb, unp_mark); 1352 } 1353 } while (unp_defer); 1354 sx_sunlock(&filelist_lock); 1355 /* 1356 * We grab an extra reference to each of the file table entries 1357 * that are not otherwise accessible and then free the rights 1358 * that are stored in messages on them. 1359 * 1360 * The bug in the orginal code is a little tricky, so I'll describe 1361 * what's wrong with it here. 1362 * 1363 * It is incorrect to simply unp_discard each entry for f_msgcount 1364 * times -- consider the case of sockets A and B that contain 1365 * references to each other. On a last close of some other socket, 1366 * we trigger a gc since the number of outstanding rights (unp_rights) 1367 * is non-zero. If during the sweep phase the gc code un_discards, 1368 * we end up doing a (full) closef on the descriptor. A closef on A 1369 * results in the following chain. Closef calls soo_close, which 1370 * calls soclose. Soclose calls first (through the switch 1371 * uipc_usrreq) unp_detach, which re-invokes unp_gc. Unp_gc simply 1372 * returns because the previous instance had set unp_gcing, and 1373 * we return all the way back to soclose, which marks the socket 1374 * with SS_NOFDREF, and then calls sofree. Sofree calls sorflush 1375 * to free up the rights that are queued in messages on the socket A, 1376 * i.e., the reference on B. The sorflush calls via the dom_dispose 1377 * switch unp_dispose, which unp_scans with unp_discard. This second 1378 * instance of unp_discard just calls closef on B. 1379 * 1380 * Well, a similar chain occurs on B, resulting in a sorflush on B, 1381 * which results in another closef on A. Unfortunately, A is already 1382 * being closed, and the descriptor has already been marked with 1383 * SS_NOFDREF, and soclose panics at this point. 1384 * 1385 * Here, we first take an extra reference to each inaccessible 1386 * descriptor. Then, we call sorflush ourself, since we know 1387 * it is a Unix domain socket anyhow. After we destroy all the 1388 * rights carried in messages, we do a last closef to get rid 1389 * of our extra reference. This is the last close, and the 1390 * unp_detach etc will shut down the socket. 1391 * 1392 * 91/09/19, bsy@cs.cmu.edu 1393 */ 1394 extra_ref = malloc(nfiles * sizeof(struct file *), M_TEMP, M_WAITOK); 1395 sx_slock(&filelist_lock); 1396 for (nunref = 0, fp = LIST_FIRST(&filehead), fpp = extra_ref; 1397 fp != NULL; fp = nextfp) { 1398 nextfp = LIST_NEXT(fp, f_list); 1399 FILE_LOCK(fp); 1400 /* 1401 * If it's not open, skip it 1402 */ 1403 if (fp->f_count == 0) { 1404 FILE_UNLOCK(fp); 1405 continue; 1406 } 1407 /* 1408 * If all refs are from msgs, and it's not marked accessible 1409 * then it must be referenced from some unreachable cycle 1410 * of (shut-down) FDs, so include it in our 1411 * list of FDs to remove 1412 */ 1413 if (fp->f_count == fp->f_msgcount && !(fp->f_gcflag & FMARK)) { 1414 *fpp++ = fp; 1415 nunref++; 1416 fp->f_count++; 1417 } 1418 FILE_UNLOCK(fp); 1419 } 1420 sx_sunlock(&filelist_lock); 1421 /* 1422 * for each FD on our hit list, do the following two things 1423 */ 1424 for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp) { 1425 struct file *tfp = *fpp; 1426 FILE_LOCK(tfp); 1427 if (tfp->f_type == DTYPE_SOCKET && 1428 tfp->f_data != NULL) { 1429 FILE_UNLOCK(tfp); 1430 sorflush(tfp->f_data); 1431 } else { 1432 FILE_UNLOCK(tfp); 1433 } 1434 } 1435 for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp) 1436 closef(*fpp, (struct thread *) NULL); 1437 free(extra_ref, M_TEMP); 1438 unp_gcing = 0; 1439 } 1440 1441 void 1442 unp_dispose(m) 1443 struct mbuf *m; 1444 { 1445 1446 if (m) 1447 unp_scan(m, unp_discard); 1448 } 1449 1450 static int 1451 unp_listen(unp, td) 1452 struct unpcb *unp; 1453 struct thread *td; 1454 { 1455 1456 cru2x(td->td_ucred, &unp->unp_peercred); 1457 unp->unp_flags |= UNP_HAVEPCCACHED; 1458 return (0); 1459 } 1460 1461 static void 1462 unp_scan(m0, op) 1463 register struct mbuf *m0; 1464 void (*op)(struct file *); 1465 { 1466 struct mbuf *m; 1467 struct file **rp; 1468 struct cmsghdr *cm; 1469 void *data; 1470 int i; 1471 socklen_t clen, datalen; 1472 int qfds; 1473 1474 while (m0 != NULL) { 1475 for (m = m0; m; m = m->m_next) { 1476 if (m->m_type != MT_CONTROL) 1477 continue; 1478 1479 cm = mtod(m, struct cmsghdr *); 1480 clen = m->m_len; 1481 1482 while (cm != NULL) { 1483 if (sizeof(*cm) > clen || cm->cmsg_len > clen) 1484 break; 1485 1486 data = CMSG_DATA(cm); 1487 datalen = (caddr_t)cm + cm->cmsg_len 1488 - (caddr_t)data; 1489 1490 if (cm->cmsg_level == SOL_SOCKET && 1491 cm->cmsg_type == SCM_RIGHTS) { 1492 qfds = datalen / sizeof (struct file *); 1493 rp = data; 1494 for (i = 0; i < qfds; i++) 1495 (*op)(*rp++); 1496 } 1497 1498 if (CMSG_SPACE(datalen) < clen) { 1499 clen -= CMSG_SPACE(datalen); 1500 cm = (struct cmsghdr *) 1501 ((caddr_t)cm + CMSG_SPACE(datalen)); 1502 } else { 1503 clen = 0; 1504 cm = NULL; 1505 } 1506 } 1507 } 1508 m0 = m0->m_act; 1509 } 1510 } 1511 1512 static void 1513 unp_mark(fp) 1514 struct file *fp; 1515 { 1516 if (fp->f_gcflag & FMARK) 1517 return; 1518 unp_defer++; 1519 fp->f_gcflag |= (FMARK|FDEFER); 1520 } 1521 1522 static void 1523 unp_discard(fp) 1524 struct file *fp; 1525 { 1526 FILE_LOCK(fp); 1527 fp->f_msgcount--; 1528 unp_rights--; 1529 FILE_UNLOCK(fp); 1530 (void) closef(fp, (struct thread *)NULL); 1531 } 1532