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