1 /* 2 * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. 3 * 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 * $Id: unusrreq.c,v 2.1 94/05/25 22:18:12 bill Exp Locker: bill $ 34 */ 35 36 #include "sys/param.h" 37 #include "sys/stat.h" 38 #include "sys/un.h" 39 #include "uio.h" 40 #include "sys/errno.h" 41 #include "proc.h" 42 #include "filedesc.h" 43 #include "domain.h" 44 #include "protosw.h" 45 #include "socketvar.h" 46 #include "unpcb.h" 47 #include "mbuf.h" 48 49 #include "namei.h" 50 #include "vnode.h" 51 52 #include "prototypes.h" 53 54 /* 55 * Unix communications domain. 56 * 57 * TODO: 58 * SEQPACKET, RDM 59 * rethink name space problems 60 * need a proper out-of-band 61 */ 62 struct sockaddr sun_noname = { sizeof(sun_noname), AF_UNIX }; 63 ino_t unp_ino; /* prototype for fake inode numbers */ 64 65 /*ARGSUSED*/ 66 uipc_usrreq(so, req, m, nam, control) 67 struct socket *so; 68 int req; 69 struct mbuf *m, *nam, *control; 70 { 71 struct unpcb *unp = sotounpcb(so); 72 register struct socket *so2; 73 register int error = 0; 74 struct proc *p = curproc; /* XXX */ 75 76 if (req == PRU_CONTROL) 77 return (EOPNOTSUPP); 78 if (req != PRU_SEND && control && control->m_len) { 79 error = EOPNOTSUPP; 80 goto release; 81 } 82 if (unp == 0 && req != PRU_ATTACH) { 83 error = EINVAL; 84 goto release; 85 } 86 switch (req) { 87 88 case PRU_ATTACH: 89 if (unp) { 90 error = EISCONN; 91 break; 92 } 93 error = unp_attach(so); 94 break; 95 96 case PRU_DETACH: 97 unp_detach(unp); 98 break; 99 100 case PRU_BIND: 101 error = unp_bind(unp, nam, p); 102 break; 103 104 case PRU_LISTEN: 105 if (unp->unp_vnode == 0) 106 error = EINVAL; 107 break; 108 109 case PRU_CONNECT: 110 error = unp_connect(so, nam, p); 111 break; 112 113 case PRU_CONNECT2: 114 error = unp_connect2(so, (struct socket *)nam); 115 break; 116 117 case PRU_DISCONNECT: 118 unp_disconnect(unp); 119 break; 120 121 case PRU_ACCEPT: 122 /* 123 * Pass back name of connected socket, 124 * if it was bound and we are still connected 125 * (our peer may have closed already!). 126 */ 127 if (unp->unp_conn && unp->unp_conn->unp_addr) { 128 nam->m_len = unp->unp_conn->unp_addr->m_len; 129 (void) memcpy(mtod(nam, caddr_t), 130 mtod(unp->unp_conn->unp_addr, caddr_t), 131 (unsigned)nam->m_len); 132 } else { 133 nam->m_len = sizeof(sun_noname); 134 *(mtod(nam, struct sockaddr *)) = sun_noname; 135 } 136 break; 137 138 case PRU_SHUTDOWN: 139 socantsendmore(so); 140 unp_shutdown(unp); 141 break; 142 143 case PRU_RCVD: 144 switch (so->so_type) { 145 146 case SOCK_DGRAM: 147 panic("uipc 1"); 148 /*NOTREACHED*/ 149 150 case SOCK_STREAM: 151 #define rcv (&so->so_rcv) 152 #define snd (&so2->so_snd) 153 if (unp->unp_conn == 0) 154 break; 155 so2 = unp->unp_conn->unp_socket; 156 /* 157 * Adjust backpressure on sender 158 * and wakeup any waiting to write. 159 */ 160 snd->sb_mbmax += unp->unp_mbcnt - rcv->sb_mbcnt; 161 unp->unp_mbcnt = rcv->sb_mbcnt; 162 snd->sb_hiwat += unp->unp_cc - rcv->sb_cc; 163 unp->unp_cc = rcv->sb_cc; 164 sowwakeup(so2); 165 #undef snd 166 #undef rcv 167 break; 168 169 default: 170 panic("uipc 2"); 171 } 172 break; 173 174 case PRU_SEND: 175 if (control && (error = unp_internalize(control, p))) 176 break; 177 switch (so->so_type) { 178 179 case SOCK_DGRAM: { 180 struct sockaddr *from; 181 182 if (nam) { 183 if (unp->unp_conn) { 184 error = EISCONN; 185 break; 186 } 187 error = unp_connect(so, nam, p); 188 if (error) 189 break; 190 } else { 191 if (unp->unp_conn == 0) { 192 error = ENOTCONN; 193 break; 194 } 195 } 196 so2 = unp->unp_conn->unp_socket; 197 if (unp->unp_addr) 198 from = mtod(unp->unp_addr, struct sockaddr *); 199 else 200 from = &sun_noname; 201 if (sbappendaddr(&so2->so_rcv, from, m, control)) { 202 sorwakeup(so2); 203 m = 0; 204 control = 0; 205 } else 206 error = ENOBUFS; 207 if (nam) 208 unp_disconnect(unp); 209 break; 210 } 211 212 case SOCK_STREAM: 213 #define rcv (&so2->so_rcv) 214 #define snd (&so->so_snd) 215 if (so->so_state & SS_CANTSENDMORE) { 216 error = EPIPE; 217 break; 218 } 219 if (unp->unp_conn == 0) 220 panic("uipc 3"); 221 so2 = unp->unp_conn->unp_socket; 222 /* 223 * Send to paired receive port, and then reduce 224 * send buffer hiwater marks to maintain backpressure. 225 * Wake up readers. 226 */ 227 if (control) { 228 if (sbappendcontrol(rcv, m, control)) 229 control = 0; 230 } else 231 sbappend(rcv, m); 232 snd->sb_mbmax -= 233 rcv->sb_mbcnt - unp->unp_conn->unp_mbcnt; 234 unp->unp_conn->unp_mbcnt = rcv->sb_mbcnt; 235 snd->sb_hiwat -= rcv->sb_cc - unp->unp_conn->unp_cc; 236 unp->unp_conn->unp_cc = rcv->sb_cc; 237 sorwakeup(so2); 238 m = 0; 239 #undef snd 240 #undef rcv 241 break; 242 243 default: 244 panic("uipc 4"); 245 } 246 break; 247 248 case PRU_ABORT: 249 unp_drop(unp, ECONNABORTED); 250 break; 251 252 case PRU_SENSE: 253 ((struct stat *) m)->st_blksize = so->so_snd.sb_hiwat; 254 if (so->so_type == SOCK_STREAM && unp->unp_conn != 0) { 255 so2 = unp->unp_conn->unp_socket; 256 ((struct stat *) m)->st_blksize += so2->so_rcv.sb_cc; 257 } 258 if (unp->unp_ino == 0) 259 unp->unp_ino = unp_ino++; 260 ((struct stat *) m)->st_ino = unp->unp_ino; 261 return (0); 262 263 case PRU_RCVOOB: 264 return (EOPNOTSUPP); 265 266 case PRU_SENDOOB: 267 error = EOPNOTSUPP; 268 break; 269 270 case PRU_SOCKADDR: 271 if (unp->unp_addr) { 272 nam->m_len = unp->unp_addr->m_len; 273 (void) memcpy(mtod(nam, caddr_t), 274 mtod(unp->unp_addr, caddr_t), 275 (unsigned)nam->m_len); 276 } else 277 nam->m_len = 0; 278 break; 279 280 case PRU_PEERADDR: 281 if (unp->unp_conn && unp->unp_conn->unp_addr) { 282 nam->m_len = unp->unp_conn->unp_addr->m_len; 283 (void) memcpy(mtod(nam, caddr_t), 284 mtod(unp->unp_conn->unp_addr, caddr_t), 285 (unsigned)nam->m_len); 286 } else 287 nam->m_len = 0; 288 break; 289 290 case PRU_SLOWTIMO: 291 break; 292 293 default: 294 panic("piusrreq"); 295 } 296 release: 297 if (control) 298 m_freem(control); 299 if (m) 300 m_freem(m); 301 return (error); 302 } 303 304 /* 305 * Both send and receive buffers are allocated PIPSIZ bytes of buffering 306 * for stream sockets, although the total for sender and receiver is 307 * actually only PIPSIZ. 308 * Datagram sockets really use the sendspace as the maximum datagram size, 309 * and don't really want to reserve the sendspace. Their recvspace should 310 * be large enough for at least one max-size datagram plus address. 311 */ 312 #define PIPSIZ 4096 313 u_long unpst_sendspace = PIPSIZ; 314 u_long unpst_recvspace = PIPSIZ; 315 u_long unpdg_sendspace = 2*1024; /* really max datagram size */ 316 u_long unpdg_recvspace = 4*1024; 317 318 int unp_rights; /* file descriptors in flight */ 319 320 unp_attach(so) 321 struct socket *so; 322 { 323 register struct mbuf *m; 324 register struct unpcb *unp; 325 int error; 326 327 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 328 switch (so->so_type) { 329 330 case SOCK_STREAM: 331 error = soreserve(so, unpst_sendspace, unpst_recvspace); 332 break; 333 334 case SOCK_DGRAM: 335 error = soreserve(so, unpdg_sendspace, unpdg_recvspace); 336 break; 337 } 338 if (error) 339 return (error); 340 } 341 m = m_getclr(M_DONTWAIT, MT_PCB); 342 if (m == NULL) 343 return (ENOBUFS); 344 unp = mtod(m, struct unpcb *); 345 so->so_pcb = (caddr_t)unp; 346 unp->unp_socket = so; 347 return (0); 348 } 349 350 unp_detach(unp) 351 register struct unpcb *unp; 352 { 353 354 if (unp->unp_vnode) { 355 unp->unp_vnode->v_socket = 0; 356 vrele(unp->unp_vnode); 357 unp->unp_vnode = 0; 358 } 359 if (unp->unp_conn) 360 unp_disconnect(unp); 361 while (unp->unp_refs) 362 unp_drop(unp->unp_refs, ECONNRESET); 363 soisdisconnected(unp->unp_socket); 364 unp->unp_socket->so_pcb = 0; 365 m_freem(unp->unp_addr); 366 (void) m_free(dtom(unp)); 367 if (unp_rights) 368 unp_gc(); 369 } 370 371 unp_bind(unp, nam, p) 372 struct unpcb *unp; 373 struct mbuf *nam; 374 struct proc *p; 375 { 376 struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *); 377 register struct vnode *vp; 378 register struct nameidata *ndp; 379 struct vattr vattr; 380 int error; 381 struct nameidata nd; 382 383 ndp = &nd; 384 ndp->ni_dirp = soun->sun_path; 385 if (unp->unp_vnode != NULL) 386 return (EINVAL); 387 if (nam->m_len == MLEN) { 388 if (*(mtod(nam, caddr_t) + nam->m_len - 1) != 0) 389 return (EINVAL); 390 } else 391 *(mtod(nam, caddr_t) + nam->m_len) = 0; 392 /* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */ 393 ndp->ni_nameiop = CREATE | FOLLOW | LOCKPARENT; 394 ndp->ni_segflg = UIO_SYSSPACE; 395 if (error = namei(ndp, p)) 396 return (error); 397 vp = ndp->ni_vp; 398 if (vp != NULL) { 399 VOP_ABORTOP(ndp); 400 if (ndp->ni_dvp == vp) 401 vrele(ndp->ni_dvp); 402 else 403 vput(ndp->ni_dvp); 404 vrele(vp); 405 return (EADDRINUSE); 406 } 407 VATTR_NULL(&vattr); 408 vattr.va_type = VSOCK; 409 vattr.va_mode = 0777; 410 if (error = VOP_CREATE(ndp, &vattr, p)) 411 return (error); 412 vp = ndp->ni_vp; 413 vp->v_socket = unp->unp_socket; 414 unp->unp_vnode = vp; 415 unp->unp_addr = m_copym(nam, 0, (int)M_COPYALL, M_WAIT); 416 VOP_UNLOCK(vp); 417 return (0); 418 } 419 420 unp_connect(so, nam, p) 421 struct socket *so; 422 struct mbuf *nam; 423 struct proc *p; 424 { 425 register struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *); 426 register struct vnode *vp; 427 register struct socket *so2, *so3; 428 register struct nameidata *ndp; 429 struct unpcb *unp2, *unp3; 430 int error; 431 struct nameidata nd; 432 433 ndp = &nd; 434 ndp->ni_dirp = soun->sun_path; 435 if (nam->m_data + nam->m_len == &nam->m_dat[MLEN]) { /* XXX */ 436 if (*(mtod(nam, caddr_t) + nam->m_len - 1) != 0) 437 return (EMSGSIZE); 438 } else 439 *(mtod(nam, caddr_t) + nam->m_len) = 0; 440 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 441 ndp->ni_segflg = UIO_SYSSPACE; 442 if (error = namei(ndp, p)) 443 return (error); 444 vp = ndp->ni_vp; 445 if (vp->v_type != VSOCK) { 446 error = ENOTSOCK; 447 goto bad; 448 } 449 if (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) 450 goto bad; 451 so2 = vp->v_socket; 452 if (so2 == 0) { 453 error = ECONNREFUSED; 454 goto bad; 455 } 456 if (so->so_type != so2->so_type) { 457 error = EPROTOTYPE; 458 goto bad; 459 } 460 if (so->so_proto->pr_flags & PR_CONNREQUIRED) { 461 if ((so2->so_options & SO_ACCEPTCONN) == 0 || 462 (so3 = sonewconn(so2, 0)) == 0) { 463 error = ECONNREFUSED; 464 goto bad; 465 } 466 unp2 = sotounpcb(so2); 467 unp3 = sotounpcb(so3); 468 if (unp2->unp_addr) 469 unp3->unp_addr = 470 m_copym(unp2->unp_addr, 0, (int)M_COPYALL, M_WAIT); 471 so2 = so3; 472 } 473 error = unp_connect2(so, so2); 474 bad: 475 vput(vp); 476 return (error); 477 } 478 479 unp_connect2(so, so2) 480 register struct socket *so; 481 register struct socket *so2; 482 { 483 register struct unpcb *unp = sotounpcb(so); 484 register struct unpcb *unp2; 485 486 if (so2->so_type != so->so_type) 487 return (EPROTOTYPE); 488 unp2 = sotounpcb(so2); 489 unp->unp_conn = unp2; 490 switch (so->so_type) { 491 492 case SOCK_DGRAM: 493 unp->unp_nextref = unp2->unp_refs; 494 unp2->unp_refs = unp; 495 soisconnected(so); 496 break; 497 498 case SOCK_STREAM: 499 unp2->unp_conn = unp; 500 soisconnected(so); 501 soisconnected(so2); 502 break; 503 504 default: 505 panic("unp_connect2"); 506 } 507 return (0); 508 } 509 510 unp_disconnect(unp) 511 struct unpcb *unp; 512 { 513 register struct unpcb *unp2 = unp->unp_conn; 514 515 if (unp2 == 0) 516 return; 517 unp->unp_conn = 0; 518 switch (unp->unp_socket->so_type) { 519 520 case SOCK_DGRAM: 521 if (unp2->unp_refs == unp) 522 unp2->unp_refs = unp->unp_nextref; 523 else { 524 unp2 = unp2->unp_refs; 525 for (;;) { 526 if (unp2 == 0) 527 panic("unp_disconnect"); 528 if (unp2->unp_nextref == unp) 529 break; 530 unp2 = unp2->unp_nextref; 531 } 532 unp2->unp_nextref = unp->unp_nextref; 533 } 534 unp->unp_nextref = 0; 535 unp->unp_socket->so_state &= ~SS_ISCONNECTED; 536 break; 537 538 case SOCK_STREAM: 539 soisdisconnected(unp->unp_socket); 540 unp2->unp_conn = 0; 541 soisdisconnected(unp2->unp_socket); 542 break; 543 } 544 } 545 546 #ifdef notdef 547 unp_abort(unp) 548 struct unpcb *unp; 549 { 550 551 unp_detach(unp); 552 } 553 #endif 554 555 unp_shutdown(unp) 556 struct unpcb *unp; 557 { 558 struct socket *so; 559 560 if (unp->unp_socket->so_type == SOCK_STREAM && unp->unp_conn && 561 (so = unp->unp_conn->unp_socket)) 562 socantrcvmore(so); 563 } 564 565 unp_drop(unp, errno) 566 struct unpcb *unp; 567 int errno; 568 { 569 struct socket *so = unp->unp_socket; 570 571 so->so_error = errno; 572 unp_disconnect(unp); 573 if (so->so_head) { 574 so->so_pcb = (caddr_t) 0; 575 m_freem(unp->unp_addr); 576 (void) m_free(dtom(unp)); 577 sofree(so); 578 } 579 } 580 581 #ifdef notdef 582 unp_drain() 583 { 584 585 } 586 #endif 587 588 unp_externalize(struct mbuf *rights, struct proc *p) 589 { 590 int i; 591 struct cmsghdr *cm = mtod(rights, struct cmsghdr *); 592 struct file **rp = (struct file **)(cm + 1); 593 struct file *fp; 594 int newfds = (cm->cmsg_len - sizeof(*cm)) / sizeof (int); 595 int f; 596 597 if (fdavail(p, newfds)) { 598 for (i = 0; i < newfds; i++) { 599 fp = *rp; 600 unp_discard(fp); 601 *rp++ = 0; /* XXX */ 602 } 603 return (EMSGSIZE); 604 } 605 606 #ifndef was 607 for (i = 0; i < newfds; i++) { 608 if (fdalloc(p, 0, &f)) 609 panic("unp_externalize"); 610 fp = *rp; 611 p->p_fd->fd_ofiles[f] = fp; 612 fp->f_msgcount--; 613 unp_rights--; 614 *(int *)rp++ = f; 615 } 616 #else 617 (int)rp = fptofd(p, rp, newfds); 618 unp_rights -= newfds; 619 #endif 620 return (0); 621 } 622 623 unp_internalize(control, p) 624 struct mbuf *control; 625 struct proc *p; 626 { 627 struct filedesc *fdp = p->p_fd; 628 register struct cmsghdr *cm = mtod(control, struct cmsghdr *); 629 register struct file **rp; 630 register struct file *fp; 631 register int i, fd; 632 int oldfds; 633 int error; 634 635 if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET || 636 cm->cmsg_len != control->m_len) 637 return (EINVAL); 638 oldfds = (cm->cmsg_len - sizeof (*cm)) / sizeof (int); 639 rp = (struct file **)(cm + 1); 640 #ifndef was 641 for (i = 0; i < oldfds; i++) { 642 fd = *(int *)rp++; 643 if ((unsigned)fd >= fdp->fd_nfiles || 644 fdp->fd_ofiles[fd] == NULL) 645 return (EBADF); 646 } 647 rp = (struct file **)(cm + 1); 648 for (i = 0; i < oldfds; i++) { 649 fp = fdp->fd_ofiles[*(int *)rp]; 650 *rp++ = fp; 651 fp->f_count++; 652 fp->f_msgcount++; 653 unp_rights++; 654 } 655 #else 656 if (error = arefdsopen(p, (int *)rp, oldfds)) 657 return (error); 658 rp = fdtofp(p, (int *)rp, oldfds); 659 unp_rights += oldfds; 660 #endif 661 return (0); 662 } 663 664 int unp_defer, unp_gcing; 665 int unp_mark(); 666 extern struct domain unixdomain; 667 668 unp_gc() 669 { 670 register struct file *fp; 671 register struct socket *so; 672 673 if (unp_gcing) 674 return; 675 unp_gcing = 1; 676 restart: 677 unp_defer = 0; 678 for (fp = filehead; fp; fp = fp->f_filef) 679 fp->f_flag &= ~(FMARK|FDEFER); 680 do { 681 for (fp = filehead; fp; fp = fp->f_filef) { 682 if (fp->f_count == 0) 683 continue; 684 if (fp->f_flag & FDEFER) { 685 fp->f_flag &= ~FDEFER; 686 unp_defer--; 687 } else { 688 if (fp->f_flag & FMARK) 689 continue; 690 if (fp->f_count == fp->f_msgcount) 691 continue; 692 fp->f_flag |= FMARK; 693 } 694 if (fp->f_type != DTYPE_SOCKET || 695 (so = (struct socket *)fp->f_data) == 0) 696 continue; 697 if (so->so_proto->pr_domain != &unixdomain || 698 (so->so_proto->pr_flags&PR_RIGHTS) == 0) 699 continue; 700 #ifdef notdef 701 if (so->so_rcv.sb_flags & SB_LOCK) { 702 /* 703 * This is problematical; it's not clear 704 * we need to wait for the sockbuf to be 705 * unlocked (on a uniprocessor, at least), 706 * and it's also not clear what to do 707 * if sbwait returns an error due to receipt 708 * of a signal. If sbwait does return 709 * an error, we'll go into an infinite 710 * loop. Delete all of this for now. 711 */ 712 (void) sbwait(&so->so_rcv); 713 goto restart; 714 } 715 #endif 716 unp_scan(so->so_rcv.sb_mb, unp_mark); 717 } 718 } while (unp_defer); 719 for (fp = filehead; fp; fp = fp->f_filef) { 720 if (fp->f_count == 0) 721 continue; 722 if (fp->f_count == fp->f_msgcount && (fp->f_flag & FMARK) == 0) 723 while (fp->f_msgcount) 724 unp_discard(fp); 725 } 726 unp_gcing = 0; 727 } 728 729 unp_dispose(m) 730 struct mbuf *m; 731 { 732 int unp_discard(); 733 734 if (m) 735 unp_scan(m, unp_discard); 736 } 737 738 unp_scan(m0, op) 739 register struct mbuf *m0; 740 int (*op)(); 741 { 742 register struct mbuf *m; 743 register struct file **rp; 744 register struct cmsghdr *cm; 745 register int i; 746 int qfds; 747 748 while (m0) { 749 for (m = m0; m; m = m->m_next) 750 if (m->m_type == MT_CONTROL && 751 m->m_len >= sizeof(*cm)) { 752 cm = mtod(m, struct cmsghdr *); 753 if (cm->cmsg_level != SOL_SOCKET || 754 cm->cmsg_type != SCM_RIGHTS) 755 continue; 756 qfds = (cm->cmsg_len - sizeof *cm) 757 / sizeof (struct file *); 758 rp = (struct file **)(cm + 1); 759 for (i = 0; i < qfds; i++) 760 (*op)(*rp++); 761 break; /* XXX, but saves time */ 762 } 763 m0 = m0->m_act; 764 } 765 } 766 767 unp_mark(fp) 768 struct file *fp; 769 { 770 771 if (fp->f_flag & FMARK) 772 return; 773 unp_defer++; 774 fp->f_flag |= (FMARK|FDEFER); 775 } 776 777 unp_discard(fp) 778 struct file *fp; 779 { 780 781 if (fp->f_msgcount == 0) 782 return; 783 fp->f_msgcount--; 784 unp_rights--; 785 (void) closef(fp, curproc); 786 } 787