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