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