1*17543Skarels /* uipc_usrreq.c 6.11 84/12/20 */ 28925Sroot 317105Sbloom #include "param.h" 417105Sbloom #include "dir.h" 517105Sbloom #include "user.h" 617105Sbloom #include "mbuf.h" 717105Sbloom #include "domain.h" 817105Sbloom #include "protosw.h" 917105Sbloom #include "socket.h" 1017105Sbloom #include "socketvar.h" 1117105Sbloom #include "unpcb.h" 1217105Sbloom #include "un.h" 1317105Sbloom #include "inode.h" 1417105Sbloom #include "file.h" 1517105Sbloom #include "stat.h" 168925Sroot 178925Sroot /* 188925Sroot * Unix communications domain. 1912760Ssam * 2012760Ssam * TODO: 2112760Ssam * SEQPACKET, RDM 2213119Ssam * rethink name space problems 2312760Ssam * need a proper out-of-band 248925Sroot */ 2513119Ssam struct sockaddr sun_noname = { AF_UNIX }; 268925Sroot 278925Sroot /*ARGSUSED*/ 2812760Ssam uipc_usrreq(so, req, m, nam, rights) 298925Sroot struct socket *so; 308925Sroot int req; 3112760Ssam struct mbuf *m, *nam, *rights; 328925Sroot { 338925Sroot struct unpcb *unp = sotounpcb(so); 348925Sroot register struct socket *so2; 358925Sroot int error = 0; 368925Sroot 3712760Ssam if (req != PRU_SEND && rights && rights->m_len) { 3812760Ssam error = EOPNOTSUPP; 3912760Ssam goto release; 4012760Ssam } 4112760Ssam if (unp == 0 && req != PRU_ATTACH) { 4212760Ssam error = EINVAL; 4312760Ssam goto release; 4412760Ssam } 458925Sroot switch (req) { 468925Sroot 478925Sroot case PRU_ATTACH: 488925Sroot if (unp) { 499169Ssam error = EISCONN; 508925Sroot break; 518925Sroot } 529028Sroot error = unp_attach(so); 538925Sroot break; 548925Sroot 558925Sroot case PRU_DETACH: 568925Sroot unp_detach(unp); 578925Sroot break; 588925Sroot 599169Ssam case PRU_BIND: 609169Ssam error = unp_bind(unp, nam); 619169Ssam break; 629169Ssam 639169Ssam case PRU_LISTEN: 649169Ssam if (unp->unp_inode == 0) 659169Ssam error = EINVAL; 669169Ssam break; 679169Ssam 688925Sroot case PRU_CONNECT: 699028Sroot error = unp_connect(so, nam); 708925Sroot break; 718925Sroot 7212760Ssam case PRU_CONNECT2: 7313115Ssam error = unp_connect2(so, (struct mbuf *)0, 7413115Ssam (struct socket *)nam); 7512760Ssam break; 7612760Ssam 778925Sroot case PRU_DISCONNECT: 788925Sroot unp_disconnect(unp); 798925Sroot break; 808925Sroot 819169Ssam case PRU_ACCEPT: 829169Ssam nam->m_len = unp->unp_remaddr->m_len; 839169Ssam bcopy(mtod(unp->unp_remaddr, caddr_t), 849169Ssam mtod(nam, caddr_t), (unsigned)nam->m_len); 858925Sroot break; 868925Sroot 878925Sroot case PRU_SHUTDOWN: 888925Sroot socantsendmore(so); 898925Sroot unp_usrclosed(unp); 908925Sroot break; 918925Sroot 928925Sroot case PRU_RCVD: 938925Sroot switch (so->so_type) { 948925Sroot 958925Sroot case SOCK_DGRAM: 968925Sroot panic("uipc 1"); 9710139Ssam /*NOTREACHED*/ 988925Sroot 9910139Ssam case SOCK_STREAM: 1008925Sroot #define rcv (&so->so_rcv) 1018925Sroot #define snd (&so2->so_snd) 1028925Sroot if (unp->unp_conn == 0) 1038925Sroot break; 1048925Sroot so2 = unp->unp_conn->unp_socket; 1058925Sroot /* 1068925Sroot * Transfer resources back to send port 1078925Sroot * and wakeup any waiting to write. 1088925Sroot */ 1098925Sroot snd->sb_mbmax += rcv->sb_mbmax - rcv->sb_mbcnt; 1108925Sroot rcv->sb_mbmax = rcv->sb_mbcnt; 1118925Sroot snd->sb_hiwat += rcv->sb_hiwat - rcv->sb_cc; 1128925Sroot rcv->sb_hiwat = rcv->sb_cc; 113*17543Skarels sowwakeup(so2); 1148925Sroot #undef snd 1158925Sroot #undef rcv 1168925Sroot break; 1178925Sroot 1188925Sroot default: 1198925Sroot panic("uipc 2"); 1208925Sroot } 1218925Sroot break; 1228925Sroot 1238925Sroot case PRU_SEND: 1248925Sroot switch (so->so_type) { 1258925Sroot 1268925Sroot case SOCK_DGRAM: 1279028Sroot if (nam) { 1288925Sroot if (unp->unp_conn) { 1298925Sroot error = EISCONN; 1308925Sroot break; 1318925Sroot } 1329028Sroot error = unp_connect(so, nam); 1338925Sroot if (error) 1348925Sroot break; 1358925Sroot } else { 1368925Sroot if (unp->unp_conn == 0) { 1378925Sroot error = ENOTCONN; 1388925Sroot break; 1398925Sroot } 1408925Sroot } 1418925Sroot so2 = unp->unp_conn->unp_socket; 1429169Ssam /* BEGIN XXX */ 14312760Ssam if (rights) { 14412760Ssam error = unp_internalize(rights); 14512760Ssam if (error) 14612760Ssam break; 14712760Ssam } 14812760Ssam if (sbspace(&so2->so_rcv) > 0) { 14913119Ssam /* 15013119Ssam * There's no record of source socket's 15113119Ssam * name, so send null name for the moment. 15213119Ssam */ 153*17543Skarels if (sbappendaddr(&so2->so_rcv, 154*17543Skarels &sun_noname, m, rights)) { 155*17543Skarels sorwakeup(so2); 156*17543Skarels m = 0; 157*17543Skarels } 15812760Ssam } 1599169Ssam /* END XXX */ 1609028Sroot if (nam) 1619169Ssam unp_disconnect(unp); 1628925Sroot break; 1638925Sroot 1648925Sroot case SOCK_STREAM: 1658925Sroot #define rcv (&so2->so_rcv) 1668925Sroot #define snd (&so->so_snd) 16712760Ssam if (rights && rights->m_len) { 16812760Ssam error = EOPNOTSUPP; 16912760Ssam break; 17012760Ssam } 1718925Sroot if (unp->unp_conn == 0) 1728925Sroot panic("uipc 3"); 1738925Sroot so2 = unp->unp_conn->unp_socket; 1748925Sroot /* 1758925Sroot * Send to paired receive port, and then 1768925Sroot * give it enough resources to hold what it already has. 1778925Sroot * Wake up readers. 1788925Sroot */ 1798925Sroot sbappend(rcv, m); 1808925Sroot snd->sb_mbmax -= rcv->sb_mbcnt - rcv->sb_mbmax; 1818925Sroot rcv->sb_mbmax = rcv->sb_mbcnt; 1828925Sroot snd->sb_hiwat -= rcv->sb_cc - rcv->sb_hiwat; 1838925Sroot rcv->sb_hiwat = rcv->sb_cc; 184*17543Skarels sorwakeup(so2); 185*17543Skarels m = 0; 1868925Sroot #undef snd 1878925Sroot #undef rcv 1888925Sroot break; 1898925Sroot 1908925Sroot default: 1918925Sroot panic("uipc 4"); 1928925Sroot } 1938925Sroot break; 1948925Sroot 1958925Sroot case PRU_ABORT: 1968925Sroot unp_drop(unp, ECONNABORTED); 1978925Sroot break; 1988925Sroot 1998925Sroot /* SOME AS YET UNIMPLEMENTED HOOKS */ 2008925Sroot case PRU_CONTROL: 20113050Ssam return (EOPNOTSUPP); 2028925Sroot 20316973Skarels /* END UNIMPLEMENTED HOOKS */ 2048925Sroot case PRU_SENSE: 20516973Skarels ((struct stat *) m)->st_blksize = so->so_snd.sb_hiwat; 20616973Skarels if (so->so_type == SOCK_STREAM && unp->unp_conn != 0) { 20716973Skarels so2 = unp->unp_conn->unp_socket; 20816973Skarels ((struct stat *) m)->st_blksize += so2->so_rcv.sb_cc; 20916973Skarels } 21016973Skarels return (0); 2118925Sroot 2128925Sroot case PRU_RCVOOB: 21316774Sbloom return (EOPNOTSUPP); 2148925Sroot 2158925Sroot case PRU_SENDOOB: 216*17543Skarels error = EOPNOTSUPP; 2178925Sroot break; 2188925Sroot 2198925Sroot case PRU_SOCKADDR: 2208925Sroot break; 2218925Sroot 22214121Ssam case PRU_PEERADDR: 22314121Ssam break; 22414121Ssam 2258925Sroot case PRU_SLOWTIMO: 2268925Sroot break; 2278925Sroot 2288925Sroot default: 2298925Sroot panic("piusrreq"); 2308925Sroot } 23112760Ssam release: 23212760Ssam if (m) 23312760Ssam m_freem(m); 23411709Ssam return (error); 2358925Sroot } 2368925Sroot 23716973Skarels /* 23816973Skarels * We assign all buffering for stream sockets to the source, 23916973Skarels * as that is where the flow control is implemented. 24016973Skarels * Datagram sockets really use the sendspace as the maximum datagram size, 24116973Skarels * and don't really want to reserve the sendspace. Their recvspace should 24216973Skarels * be large enough for at least one max-size datagram plus address. 24316973Skarels */ 24416973Skarels #define PIPSIZ 4096 24516973Skarels int unpst_sendspace = PIPSIZ; 24616973Skarels int unpst_recvspace = 0; 24716973Skarels int unpdg_sendspace = 2*1024; /* really max datagram size */ 24816973Skarels int unpdg_recvspace = 4*1024; 2498925Sroot 2509169Ssam unp_attach(so) 2518925Sroot struct socket *so; 2528925Sroot { 2539169Ssam register struct mbuf *m; 2548925Sroot register struct unpcb *unp; 2558925Sroot int error; 2568925Sroot 25716973Skarels switch (so->so_type) { 25816973Skarels 25916973Skarels case SOCK_STREAM: 26016973Skarels error = soreserve(so, unpst_sendspace, unpst_recvspace); 26116973Skarels break; 26216973Skarels 26316973Skarels case SOCK_DGRAM: 26416973Skarels error = soreserve(so, unpdg_sendspace, unpdg_recvspace); 26516973Skarels break; 26616973Skarels } 2678925Sroot if (error) 26810139Ssam return (error); 2699637Ssam m = m_getclr(M_DONTWAIT, MT_PCB); 27010139Ssam if (m == NULL) 27110139Ssam return (ENOBUFS); 2728925Sroot unp = mtod(m, struct unpcb *); 2738925Sroot so->so_pcb = (caddr_t)unp; 2748925Sroot unp->unp_socket = so; 2758925Sroot return (0); 2768925Sroot } 2778925Sroot 2788925Sroot unp_detach(unp) 2799169Ssam register struct unpcb *unp; 2808925Sroot { 2818925Sroot 2828925Sroot if (unp->unp_inode) { 28317020Skarels unp->unp_inode->i_socket = 0; 2848925Sroot irele(unp->unp_inode); 2858925Sroot unp->unp_inode = 0; 2868925Sroot } 2878925Sroot if (unp->unp_conn) 2888925Sroot unp_disconnect(unp); 2898925Sroot while (unp->unp_refs) 2908925Sroot unp_drop(unp->unp_refs, ECONNRESET); 2918925Sroot soisdisconnected(unp->unp_socket); 2928925Sroot unp->unp_socket->so_pcb = 0; 2939169Ssam m_freem(unp->unp_remaddr); 2949169Ssam (void) m_free(dtom(unp)); 2958925Sroot } 2968925Sroot 2979169Ssam unp_bind(unp, nam) 2988925Sroot struct unpcb *unp; 2999169Ssam struct mbuf *nam; 3008925Sroot { 3019169Ssam struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *); 3028925Sroot register struct inode *ip; 30316695Smckusick register struct nameidata *ndp = &u.u_nd; 3048925Sroot int error; 3058925Sroot 30616695Smckusick ndp->ni_dirp = soun->sun_path; 30712760Ssam if (nam->m_len == MLEN) 30812760Ssam return (EINVAL); 30912760Ssam *(mtod(nam, caddr_t) + nam->m_len) = 0; 31012760Ssam /* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */ 31116695Smckusick ndp->ni_nameiop = CREATE | FOLLOW; 31216695Smckusick ndp->ni_segflg = UIO_SYSSPACE; 31316695Smckusick ip = namei(ndp); 3148925Sroot if (ip) { 3158925Sroot iput(ip); 31610139Ssam return (EADDRINUSE); 3178925Sroot } 31811828Ssam if (error = u.u_error) { 31911828Ssam u.u_error = 0; /* XXX */ 32011828Ssam return (error); 32111828Ssam } 32216695Smckusick ip = maknode(IFSOCK | 0777, ndp); 3238925Sroot if (ip == NULL) { 3248925Sroot error = u.u_error; /* XXX */ 3258925Sroot u.u_error = 0; /* XXX */ 3268925Sroot return (error); 3278925Sroot } 3288925Sroot ip->i_socket = unp->unp_socket; 3298925Sroot unp->unp_inode = ip; 3308925Sroot iunlock(ip); /* but keep reference */ 3318925Sroot return (0); 3328925Sroot } 3338925Sroot 3349169Ssam unp_connect(so, nam) 3358925Sroot struct socket *so; 3369169Ssam struct mbuf *nam; 3378925Sroot { 3389169Ssam register struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *); 3399169Ssam register struct inode *ip; 3408925Sroot int error; 34112760Ssam register struct socket *so2; 34216695Smckusick register struct nameidata *ndp = &u.u_nd; 3438925Sroot 34416695Smckusick ndp->ni_dirp = soun->sun_path; 34512760Ssam if (nam->m_len + (nam->m_off - MMINOFF) == MLEN) 34612760Ssam return (EMSGSIZE); 34712760Ssam *(mtod(nam, caddr_t) + nam->m_len) = 0; 34816695Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW; 34916695Smckusick ndp->ni_segflg = UIO_SYSSPACE; 35016695Smckusick ip = namei(ndp); 3518925Sroot if (ip == 0) { 3528925Sroot error = u.u_error; 3538925Sroot u.u_error = 0; 35410139Ssam return (error); /* XXX */ 3558925Sroot } 356*17543Skarels if (access(ip, IWRITE)) { 357*17543Skarels error = u.u_error; 358*17543Skarels u.u_error = 0; /* XXX */ 359*17543Skarels goto bad; 360*17543Skarels } 3618925Sroot if ((ip->i_mode&IFMT) != IFSOCK) { 3628925Sroot error = ENOTSOCK; 3638925Sroot goto bad; 3648925Sroot } 3658925Sroot so2 = ip->i_socket; 3668925Sroot if (so2 == 0) { 3678925Sroot error = ECONNREFUSED; 3688925Sroot goto bad; 3698925Sroot } 37013115Ssam if (so->so_type != so2->so_type) { 37113115Ssam error = EPROTOTYPE; 37213115Ssam goto bad; 37313115Ssam } 37413115Ssam if (so->so_proto->pr_flags & PR_CONNREQUIRED && 37513115Ssam ((so2->so_options&SO_ACCEPTCONN) == 0 || 37613115Ssam (so2 = sonewconn(so2)) == 0)) { 37713115Ssam error = ECONNREFUSED; 37813115Ssam goto bad; 37913115Ssam } 38012760Ssam error = unp_connect2(so, nam, so2); 38112760Ssam bad: 38212760Ssam iput(ip); 38312760Ssam return (error); 38412760Ssam } 38512760Ssam 38612760Ssam unp_connect2(so, sonam, so2) 38712760Ssam register struct socket *so; 38812760Ssam struct mbuf *sonam; 38912760Ssam register struct socket *so2; 39012760Ssam { 39112760Ssam register struct unpcb *unp = sotounpcb(so); 39212760Ssam register struct unpcb *unp2; 39312760Ssam 39412760Ssam if (so2->so_type != so->so_type) 39512760Ssam return (EPROTOTYPE); 39614049Ssam unp2 = sotounpcb(so2); 39714049Ssam unp->unp_conn = unp2; 3988925Sroot switch (so->so_type) { 3998925Sroot 4008925Sroot case SOCK_DGRAM: 4018925Sroot unp->unp_nextref = unp2->unp_refs; 4028925Sroot unp2->unp_refs = unp; 403*17543Skarels soisconnected(so); 4048925Sroot break; 4058925Sroot 4068925Sroot case SOCK_STREAM: 4079169Ssam unp2->unp_conn = unp; 40812760Ssam if (sonam) 40912760Ssam unp2->unp_remaddr = m_copy(sonam, 0, (int)M_COPYALL); 41014049Ssam soisconnected(so2); 41114049Ssam soisconnected(so); 4128925Sroot break; 4138925Sroot 4148925Sroot default: 41512760Ssam panic("unp_connect2"); 4168925Sroot } 4178925Sroot return (0); 4188925Sroot } 4199169Ssam 4209169Ssam unp_disconnect(unp) 4219169Ssam struct unpcb *unp; 4229169Ssam { 4239169Ssam register struct unpcb *unp2 = unp->unp_conn; 4249169Ssam 4259169Ssam if (unp2 == 0) 4269169Ssam return; 4279169Ssam unp->unp_conn = 0; 4289169Ssam switch (unp->unp_socket->so_type) { 4299169Ssam 4309169Ssam case SOCK_DGRAM: 4319169Ssam if (unp2->unp_refs == unp) 4329169Ssam unp2->unp_refs = unp->unp_nextref; 4339169Ssam else { 4349169Ssam unp2 = unp2->unp_refs; 4359169Ssam for (;;) { 4369169Ssam if (unp2 == 0) 4379169Ssam panic("unp_disconnect"); 4389169Ssam if (unp2->unp_nextref == unp) 4399169Ssam break; 4409169Ssam unp2 = unp2->unp_nextref; 4419169Ssam } 4429169Ssam unp2->unp_nextref = unp->unp_nextref; 4439169Ssam } 4449169Ssam unp->unp_nextref = 0; 4459169Ssam break; 4469169Ssam 4479169Ssam case SOCK_STREAM: 44814049Ssam soisdisconnected(unp->unp_socket); 4499169Ssam unp2->unp_conn = 0; 4509169Ssam soisdisconnected(unp2->unp_socket); 4519169Ssam break; 4529169Ssam } 4539169Ssam } 4549169Ssam 45512760Ssam #ifdef notdef 4569169Ssam unp_abort(unp) 4579169Ssam struct unpcb *unp; 4589169Ssam { 4599169Ssam 4609169Ssam unp_detach(unp); 4619169Ssam } 46212760Ssam #endif 4639169Ssam 4649169Ssam /*ARGSUSED*/ 4659169Ssam unp_usrclosed(unp) 4669169Ssam struct unpcb *unp; 4679169Ssam { 4689169Ssam 4699169Ssam } 4709169Ssam 4719169Ssam unp_drop(unp, errno) 4729169Ssam struct unpcb *unp; 4739169Ssam int errno; 4749169Ssam { 47516054Skarels struct socket *so = unp->unp_socket; 4769169Ssam 47716054Skarels so->so_error = errno; 4789169Ssam unp_disconnect(unp); 47916054Skarels if (so->so_head) { 48016054Skarels so->so_pcb = (caddr_t) 0; 48116431Skarels m_freem(unp->unp_remaddr); 48216054Skarels (void) m_free(dtom(unp)); 48316054Skarels sofree(so); 48416054Skarels } 4859169Ssam } 4869169Ssam 48712760Ssam #ifdef notdef 4889169Ssam unp_drain() 4899169Ssam { 4909169Ssam 4919169Ssam } 49212760Ssam #endif 49312760Ssam 49412760Ssam unp_externalize(rights) 49512760Ssam struct mbuf *rights; 49612760Ssam { 49712760Ssam int newfds = rights->m_len / sizeof (int); 49812760Ssam register int i; 49912760Ssam register struct file **rp = mtod(rights, struct file **); 50012760Ssam register struct file *fp; 50112760Ssam int f; 50212760Ssam 50312760Ssam if (newfds > ufavail()) { 50412760Ssam for (i = 0; i < newfds; i++) { 50512760Ssam fp = *rp; 50612760Ssam unp_discard(fp); 50712760Ssam *rp++ = 0; 50812760Ssam } 50912760Ssam return (EMSGSIZE); 51012760Ssam } 51112760Ssam for (i = 0; i < newfds; i++) { 51212760Ssam f = ufalloc(0); 51312760Ssam if (f < 0) 51412760Ssam panic("unp_externalize"); 51512760Ssam fp = *rp; 51612760Ssam u.u_ofile[f] = fp; 51712760Ssam fp->f_msgcount--; 51814927Smckusick *(int *)rp++ = f; 51912760Ssam } 52012760Ssam return (0); 52112760Ssam } 52212760Ssam 52312760Ssam unp_internalize(rights) 52412760Ssam struct mbuf *rights; 52512760Ssam { 52612760Ssam register struct file **rp; 52712760Ssam int oldfds = rights->m_len / sizeof (int); 52812760Ssam register int i; 52912760Ssam register struct file *fp; 53012760Ssam 53112760Ssam rp = mtod(rights, struct file **); 53213084Ssam for (i = 0; i < oldfds; i++) 53312760Ssam if (getf(*(int *)rp++) == 0) 53412760Ssam return (EBADF); 53512760Ssam rp = mtod(rights, struct file **); 53613084Ssam for (i = 0; i < oldfds; i++) { 53712760Ssam fp = getf(*(int *)rp); 53812760Ssam *rp++ = fp; 53912760Ssam fp->f_count++; 54012760Ssam fp->f_msgcount++; 54112760Ssam } 54212760Ssam return (0); 54312760Ssam } 54412760Ssam 54512760Ssam int unp_defer, unp_gcing; 54612760Ssam int unp_mark(); 54716995Skarels extern struct domain unixdomain; 54812760Ssam 54912760Ssam unp_gc() 55012760Ssam { 55112760Ssam register struct file *fp; 55212760Ssam register struct socket *so; 55312760Ssam 55412760Ssam if (unp_gcing) 55512760Ssam return; 55612760Ssam unp_gcing = 1; 55712760Ssam restart: 55812760Ssam unp_defer = 0; 55912760Ssam for (fp = file; fp < fileNFILE; fp++) 56012760Ssam fp->f_flag &= ~(FMARK|FDEFER); 56112760Ssam do { 56212760Ssam for (fp = file; fp < fileNFILE; fp++) { 56312760Ssam if (fp->f_count == 0) 56412760Ssam continue; 56512760Ssam if (fp->f_flag & FDEFER) { 56612760Ssam fp->f_flag &= ~FDEFER; 56712760Ssam unp_defer--; 56812760Ssam } else { 56912760Ssam if (fp->f_flag & FMARK) 57012760Ssam continue; 57112760Ssam if (fp->f_count == fp->f_msgcount) 57212760Ssam continue; 57312760Ssam fp->f_flag |= FMARK; 57412760Ssam } 57512760Ssam if (fp->f_type != DTYPE_SOCKET) 57612760Ssam continue; 57712760Ssam so = (struct socket *)fp->f_data; 57816995Skarels if (so->so_proto->pr_domain != &unixdomain || 57912760Ssam (so->so_proto->pr_flags&PR_ADDR) == 0) 58012760Ssam continue; 58112760Ssam if (so->so_rcv.sb_flags & SB_LOCK) { 58212760Ssam sbwait(&so->so_rcv); 58312760Ssam goto restart; 58412760Ssam } 58512760Ssam unp_scan(so->so_rcv.sb_mb, unp_mark); 58612760Ssam } 58712760Ssam } while (unp_defer); 58812760Ssam for (fp = file; fp < fileNFILE; fp++) { 58912760Ssam if (fp->f_count == 0) 59012760Ssam continue; 59112760Ssam if (fp->f_count == fp->f_msgcount && (fp->f_flag&FMARK)==0) { 59212760Ssam if (fp->f_type != DTYPE_SOCKET) 59312760Ssam panic("unp_gc"); 59412760Ssam (void) soshutdown((struct socket *)fp->f_data, 0); 59512760Ssam } 59612760Ssam } 59712760Ssam unp_gcing = 0; 59812760Ssam } 59912760Ssam 60016995Skarels unp_dispose(m) 60116995Skarels struct mbuf *m; 60216995Skarels { 60316995Skarels int unp_discard(); 60416995Skarels 60517020Skarels if (m) 60617020Skarels unp_scan(m, unp_discard); 60716995Skarels } 60816995Skarels 60916995Skarels unp_scan(m0, op) 61016995Skarels register struct mbuf *m0; 61112760Ssam int (*op)(); 61212760Ssam { 61316995Skarels register struct mbuf *m; 61412760Ssam register struct file **rp; 61512760Ssam register int i; 61617020Skarels int qfds; 61712760Ssam 61816995Skarels while (m0) { 61916995Skarels for (m = m0; m; m = m->m_next) 62016995Skarels if (m->m_type == MT_RIGHTS && m->m_len) { 62116995Skarels qfds = m->m_len / sizeof (struct file *); 62216995Skarels rp = mtod(m, struct file **); 62316995Skarels for (i = 0; i < qfds; i++) 62416995Skarels (*op)(*rp++); 62516995Skarels break; /* XXX, but saves time */ 62616995Skarels } 62717020Skarels m0 = m0->m_act; 62812760Ssam } 62912760Ssam } 63012760Ssam 63112760Ssam unp_mark(fp) 63212760Ssam struct file *fp; 63312760Ssam { 63412760Ssam 63512760Ssam if (fp->f_flag & FMARK) 63612760Ssam return; 63712760Ssam unp_defer++; 63812760Ssam fp->f_flag |= (FMARK|FDEFER); 63912760Ssam } 64012760Ssam 64112760Ssam unp_discard(fp) 64212760Ssam struct file *fp; 64312760Ssam { 64412760Ssam 64512760Ssam fp->f_msgcount--; 64613084Ssam closef(fp); 64712760Ssam } 648