integrate back branch -r7.2.1.1
[unix-history] / usr / src / sys / kern / uipc_usrreq.c
CommitLineData
da7c5cc6 1/*
0880b18e 2 * Copyright (c) 1982, 1986 Regents of the University of California.
96e6449f 3 * All rights reserved.
da7c5cc6 4 *
96e6449f 5 * Redistribution and use in source and binary forms are permitted
616d42db
KB
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
96e6449f 16 *
6d47a3da 17 * @(#)uipc_usrreq.c 7.9 (Berkeley) %G%
da7c5cc6 18 */
d6213d15 19
94368568
JB
20#include "param.h"
21#include "dir.h"
22#include "user.h"
23#include "mbuf.h"
24#include "domain.h"
25#include "protosw.h"
26#include "socket.h"
27#include "socketvar.h"
28#include "unpcb.h"
29#include "un.h"
30#include "inode.h"
31#include "file.h"
32#include "stat.h"
d6213d15
BJ
33
34/*
35 * Unix communications domain.
88a7a62a
SL
36 *
37 * TODO:
38 * SEQPACKET, RDM
8ecea7bc 39 * rethink name space problems
88a7a62a 40 * need a proper out-of-band
d6213d15 41 */
a2aebb63 42struct sockaddr sun_noname = { sizeof(sun_noname), AF_UNIX };
6c0894dd 43ino_t unp_ino; /* prototype for fake inode numbers */
d6213d15
BJ
44
45/*ARGSUSED*/
88a7a62a 46uipc_usrreq(so, req, m, nam, rights)
d6213d15
BJ
47 struct socket *so;
48 int req;
88a7a62a 49 struct mbuf *m, *nam, *rights;
d6213d15
BJ
50{
51 struct unpcb *unp = sotounpcb(so);
52 register struct socket *so2;
53 int error = 0;
54
50b20c78
MK
55 if (req == PRU_CONTROL)
56 return (EOPNOTSUPP);
88a7a62a
SL
57 if (req != PRU_SEND && rights && rights->m_len) {
58 error = EOPNOTSUPP;
59 goto release;
60 }
61 if (unp == 0 && req != PRU_ATTACH) {
62 error = EINVAL;
63 goto release;
64 }
d6213d15
BJ
65 switch (req) {
66
67 case PRU_ATTACH:
68 if (unp) {
4f083fd7 69 error = EISCONN;
d6213d15
BJ
70 break;
71 }
fca5570f 72 error = unp_attach(so);
d6213d15
BJ
73 break;
74
75 case PRU_DETACH:
76 unp_detach(unp);
77 break;
78
4f083fd7
SL
79 case PRU_BIND:
80 error = unp_bind(unp, nam);
81 break;
82
83 case PRU_LISTEN:
84 if (unp->unp_inode == 0)
85 error = EINVAL;
86 break;
87
d6213d15 88 case PRU_CONNECT:
fca5570f 89 error = unp_connect(so, nam);
d6213d15
BJ
90 break;
91
88a7a62a 92 case PRU_CONNECT2:
d97afdcc 93 error = unp_connect2(so, (struct socket *)nam);
88a7a62a
SL
94 break;
95
d6213d15
BJ
96 case PRU_DISCONNECT:
97 unp_disconnect(unp);
98 break;
99
4f083fd7 100 case PRU_ACCEPT:
4aa1832d
MK
101 /*
102 * Pass back name of connected socket,
103 * if it was bound and we are still connected
104 * (our peer may have closed already!).
105 */
106 if (unp->unp_conn && unp->unp_conn->unp_addr) {
6c0894dd
MK
107 nam->m_len = unp->unp_conn->unp_addr->m_len;
108 bcopy(mtod(unp->unp_conn->unp_addr, caddr_t),
109 mtod(nam, caddr_t), (unsigned)nam->m_len);
110 } else {
111 nam->m_len = sizeof(sun_noname);
112 *(mtod(nam, struct sockaddr *)) = sun_noname;
113 }
d6213d15
BJ
114 break;
115
116 case PRU_SHUTDOWN:
117 socantsendmore(so);
118 unp_usrclosed(unp);
119 break;
d6213d15
BJ
120
121 case PRU_RCVD:
122 switch (so->so_type) {
123
124 case SOCK_DGRAM:
125 panic("uipc 1");
5fe6f9d1 126 /*NOTREACHED*/
d6213d15 127
5fe6f9d1 128 case SOCK_STREAM:
d6213d15
BJ
129#define rcv (&so->so_rcv)
130#define snd (&so2->so_snd)
131 if (unp->unp_conn == 0)
132 break;
133 so2 = unp->unp_conn->unp_socket;
134 /*
6c0894dd 135 * Adjust backpressure on sender
d6213d15
BJ
136 * and wakeup any waiting to write.
137 */
6c0894dd
MK
138 snd->sb_mbmax += unp->unp_mbcnt - rcv->sb_mbcnt;
139 unp->unp_mbcnt = rcv->sb_mbcnt;
140 snd->sb_hiwat += unp->unp_cc - rcv->sb_cc;
141 unp->unp_cc = rcv->sb_cc;
9c40f33e 142 sowwakeup(so2);
d6213d15
BJ
143#undef snd
144#undef rcv
d6213d15
BJ
145 break;
146
147 default:
148 panic("uipc 2");
149 }
150 break;
151
152 case PRU_SEND:
6c0894dd
MK
153 if (rights) {
154 error = unp_internalize(rights);
155 if (error)
156 break;
157 }
d6213d15
BJ
158 switch (so->so_type) {
159
6c0894dd
MK
160 case SOCK_DGRAM: {
161 struct sockaddr *from;
162
fca5570f 163 if (nam) {
d6213d15
BJ
164 if (unp->unp_conn) {
165 error = EISCONN;
166 break;
167 }
fca5570f 168 error = unp_connect(so, nam);
d6213d15
BJ
169 if (error)
170 break;
171 } else {
172 if (unp->unp_conn == 0) {
173 error = ENOTCONN;
174 break;
175 }
176 }
177 so2 = unp->unp_conn->unp_socket;
6c0894dd
MK
178 if (unp->unp_addr)
179 from = mtod(unp->unp_addr, struct sockaddr *);
180 else
181 from = &sun_noname;
182 if (sbspace(&so2->so_rcv) > 0 &&
183 sbappendaddr(&so2->so_rcv, from, m, rights)) {
184 sorwakeup(so2);
185 m = 0;
186 } else
187 error = ENOBUFS;
fca5570f 188 if (nam)
4f083fd7 189 unp_disconnect(unp);
d6213d15 190 break;
6c0894dd 191 }
d6213d15
BJ
192
193 case SOCK_STREAM:
194#define rcv (&so2->so_rcv)
195#define snd (&so->so_snd)
7068721c
MK
196 if (so->so_state & SS_CANTSENDMORE) {
197 error = EPIPE;
198 break;
199 }
d6213d15
BJ
200 if (unp->unp_conn == 0)
201 panic("uipc 3");
202 so2 = unp->unp_conn->unp_socket;
203 /*
6c0894dd
MK
204 * Send to paired receive port, and then reduce
205 * send buffer hiwater marks to maintain backpressure.
d6213d15
BJ
206 * Wake up readers.
207 */
6c0894dd 208 if (rights)
8011f5df 209 (void)sbappendrights(rcv, m, rights);
6c0894dd
MK
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;
9c40f33e
MK
217 sorwakeup(so2);
218 m = 0;
d6213d15
BJ
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
bfd4e82c
MK
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 }
0abd16a9 238 ((struct stat *) m)->st_dev = NODEV;
6c0894dd
MK
239 if (unp->unp_ino == 0)
240 unp->unp_ino = unp_ino++;
241 ((struct stat *) m)->st_ino = unp->unp_ino;
bfd4e82c 242 return (0);
d6213d15
BJ
243
244 case PRU_RCVOOB:
913b2f19 245 return (EOPNOTSUPP);
d6213d15
BJ
246
247 case PRU_SENDOOB:
9c40f33e 248 error = EOPNOTSUPP;
d6213d15
BJ
249 break;
250
251 case PRU_SOCKADDR:
e14f40ae
MK
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;
d6213d15
BJ
258 break;
259
a7343092 260 case PRU_PEERADDR:
bbd1716e
MK
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),
336a1154 264 mtod(nam, caddr_t), (unsigned)nam->m_len);
e14f40ae
MK
265 } else
266 nam->m_len = 0;
a7343092
SL
267 break;
268
d6213d15
BJ
269 case PRU_SLOWTIMO:
270 break;
271
272 default:
273 panic("piusrreq");
274 }
88a7a62a
SL
275release:
276 if (m)
277 m_freem(m);
e14b8185 278 return (error);
d6213d15
BJ
279}
280
bfd4e82c 281/*
6c0894dd
MK
282 * Both send and receive buffers are allocated PIPSIZ bytes of buffering
283 * for stream sockets, although the total for sender and receiver is
284 * actually only PIPSIZ.
bfd4e82c
MK
285 * Datagram sockets really use the sendspace as the maximum datagram size,
286 * and don't really want to reserve the sendspace. Their recvspace should
287 * be large enough for at least one max-size datagram plus address.
288 */
289#define PIPSIZ 4096
4f5156ea
MK
290u_long unpst_sendspace = PIPSIZ;
291u_long unpst_recvspace = PIPSIZ;
292u_long unpdg_sendspace = 2*1024; /* really max datagram size */
293u_long unpdg_recvspace = 4*1024;
d6213d15 294
6c0894dd
MK
295int unp_rights; /* file descriptors in flight */
296
4f083fd7 297unp_attach(so)
d6213d15 298 struct socket *so;
d6213d15 299{
4f083fd7 300 register struct mbuf *m;
d6213d15 301 register struct unpcb *unp;
d6213d15
BJ
302 int error;
303
4f5156ea
MK
304 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
305 switch (so->so_type) {
bfd4e82c 306
4f5156ea
MK
307 case SOCK_STREAM:
308 error = soreserve(so, unpst_sendspace, unpst_recvspace);
309 break;
bfd4e82c 310
4f5156ea
MK
311 case SOCK_DGRAM:
312 error = soreserve(so, unpdg_sendspace, unpdg_recvspace);
313 break;
314 }
315 if (error)
316 return (error);
bfd4e82c 317 }
cce93e4b 318 m = m_getclr(M_DONTWAIT, MT_PCB);
5fe6f9d1
SL
319 if (m == NULL)
320 return (ENOBUFS);
d6213d15
BJ
321 unp = mtod(m, struct unpcb *);
322 so->so_pcb = (caddr_t)unp;
323 unp->unp_socket = so;
d6213d15 324 return (0);
d6213d15
BJ
325}
326
d6213d15 327unp_detach(unp)
4f083fd7 328 register struct unpcb *unp;
d6213d15
BJ
329{
330
331 if (unp->unp_inode) {
148703ec 332 unp->unp_inode->i_socket = 0;
d6213d15
BJ
333 irele(unp->unp_inode);
334 unp->unp_inode = 0;
335 }
336 if (unp->unp_conn)
337 unp_disconnect(unp);
338 while (unp->unp_refs)
339 unp_drop(unp->unp_refs, ECONNRESET);
340 soisdisconnected(unp->unp_socket);
341 unp->unp_socket->so_pcb = 0;
6c0894dd 342 m_freem(unp->unp_addr);
4f083fd7 343 (void) m_free(dtom(unp));
6c0894dd
MK
344 if (unp_rights)
345 unp_gc();
d6213d15
BJ
346}
347
4f083fd7 348unp_bind(unp, nam)
d6213d15 349 struct unpcb *unp;
4f083fd7 350 struct mbuf *nam;
d6213d15 351{
4f083fd7 352 struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *);
d6213d15 353 register struct inode *ip;
715baff1 354 register struct nameidata *ndp = &u.u_nd;
4f083fd7 355 int error;
d6213d15 356
715baff1 357 ndp->ni_dirp = soun->sun_path;
61375223 358 if (unp->unp_inode != NULL)
88a7a62a 359 return (EINVAL);
61375223
MK
360 if (nam->m_len == MLEN) {
361 if (*(mtod(nam, caddr_t) + nam->m_len - 1) != 0)
362 return (EINVAL);
363 } else
364 *(mtod(nam, caddr_t) + nam->m_len) = 0;
88a7a62a 365/* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */
715baff1
KM
366 ndp->ni_nameiop = CREATE | FOLLOW;
367 ndp->ni_segflg = UIO_SYSSPACE;
368 ip = namei(ndp);
d6213d15
BJ
369 if (ip) {
370 iput(ip);
5fe6f9d1 371 return (EADDRINUSE);
d6213d15 372 }
f3bb1ae7
SL
373 if (error = u.u_error) {
374 u.u_error = 0; /* XXX */
375 return (error);
376 }
715baff1 377 ip = maknode(IFSOCK | 0777, ndp);
d6213d15
BJ
378 if (ip == NULL) {
379 error = u.u_error; /* XXX */
380 u.u_error = 0; /* XXX */
381 return (error);
382 }
383 ip->i_socket = unp->unp_socket;
384 unp->unp_inode = ip;
6c0894dd 385 unp->unp_addr = m_copy(nam, 0, (int)M_COPYALL);
d6213d15
BJ
386 iunlock(ip); /* but keep reference */
387 return (0);
388}
389
4f083fd7 390unp_connect(so, nam)
d6213d15 391 struct socket *so;
4f083fd7 392 struct mbuf *nam;
d6213d15 393{
4f083fd7 394 register struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *);
4f083fd7 395 register struct inode *ip;
e14f40ae 396 register struct socket *so2, *so3;
715baff1 397 register struct nameidata *ndp = &u.u_nd;
e14f40ae
MK
398 struct unpcb *unp2, *unp3;
399 int error;
d6213d15 400
715baff1 401 ndp->ni_dirp = soun->sun_path;
61375223
MK
402 if (nam->m_data + nam->m_len == &nam->m_dat[MLEN]) { /* XXX */
403 if (*(mtod(nam, caddr_t) + nam->m_len - 1) != 0)
404 return (EMSGSIZE);
405 } else
406 *(mtod(nam, caddr_t) + nam->m_len) = 0;
715baff1
KM
407 ndp->ni_nameiop = LOOKUP | FOLLOW;
408 ndp->ni_segflg = UIO_SYSSPACE;
409 ip = namei(ndp);
d6213d15
BJ
410 if (ip == 0) {
411 error = u.u_error;
412 u.u_error = 0;
5fe6f9d1 413 return (error); /* XXX */
d6213d15 414 }
9c40f33e
MK
415 if (access(ip, IWRITE)) {
416 error = u.u_error;
417 u.u_error = 0; /* XXX */
418 goto bad;
419 }
d6213d15
BJ
420 if ((ip->i_mode&IFMT) != IFSOCK) {
421 error = ENOTSOCK;
422 goto bad;
423 }
424 so2 = ip->i_socket;
425 if (so2 == 0) {
426 error = ECONNREFUSED;
427 goto bad;
428 }
5a48956d
SL
429 if (so->so_type != so2->so_type) {
430 error = EPROTOTYPE;
431 goto bad;
432 }
e14f40ae
MK
433 if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
434 if ((so2->so_options & SO_ACCEPTCONN) == 0 ||
435 (so3 = sonewconn(so2)) == 0) {
436 error = ECONNREFUSED;
437 goto bad;
438 }
439 unp2 = sotounpcb(so2);
440 unp3 = sotounpcb(so3);
441 if (unp2->unp_addr)
a2aebb63
KS
442 unp3->unp_addr =
443 m_copy(unp2->unp_addr, 0, (int)M_COPYALL);
e14f40ae 444 so2 = so3;
5a48956d 445 }
d97afdcc 446 error = unp_connect2(so, so2);
88a7a62a
SL
447bad:
448 iput(ip);
449 return (error);
450}
451
d97afdcc 452unp_connect2(so, so2)
88a7a62a 453 register struct socket *so;
88a7a62a
SL
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);
ccffacbd
SL
461 unp2 = sotounpcb(so2);
462 unp->unp_conn = unp2;
d6213d15
BJ
463 switch (so->so_type) {
464
465 case SOCK_DGRAM:
d6213d15
BJ
466 unp->unp_nextref = unp2->unp_refs;
467 unp2->unp_refs = unp;
9c40f33e 468 soisconnected(so);
d6213d15
BJ
469 break;
470
471 case SOCK_STREAM:
4f083fd7 472 unp2->unp_conn = unp;
ccffacbd
SL
473 soisconnected(so2);
474 soisconnected(so);
d6213d15
BJ
475 break;
476
477 default:
88a7a62a 478 panic("unp_connect2");
d6213d15 479 }
d6213d15 480 return (0);
d6213d15 481}
4f083fd7
SL
482
483unp_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;
4f083fd7
SL
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;
c5935bca 508 unp->unp_socket->so_state &= ~SS_ISCONNECTED;
4f083fd7
SL
509 break;
510
511 case SOCK_STREAM:
ccffacbd 512 soisdisconnected(unp->unp_socket);
4f083fd7
SL
513 unp2->unp_conn = 0;
514 soisdisconnected(unp2->unp_socket);
4f083fd7
SL
515 break;
516 }
517}
518
88a7a62a 519#ifdef notdef
4f083fd7
SL
520unp_abort(unp)
521 struct unpcb *unp;
522{
523
524 unp_detach(unp);
525}
88a7a62a 526#endif
4f083fd7
SL
527
528/*ARGSUSED*/
529unp_usrclosed(unp)
530 struct unpcb *unp;
531{
532
533}
534
535unp_drop(unp, errno)
536 struct unpcb *unp;
537 int errno;
538{
d12671e0 539 struct socket *so = unp->unp_socket;
4f083fd7 540
d12671e0 541 so->so_error = errno;
4f083fd7 542 unp_disconnect(unp);
d12671e0
MK
543 if (so->so_head) {
544 so->so_pcb = (caddr_t) 0;
6c0894dd 545 m_freem(unp->unp_addr);
d12671e0
MK
546 (void) m_free(dtom(unp));
547 sofree(so);
548 }
4f083fd7
SL
549}
550
88a7a62a 551#ifdef notdef
4f083fd7
SL
552unp_drain()
553{
554
555}
88a7a62a
SL
556#endif
557
558unp_externalize(rights)
559 struct mbuf *rights;
560{
561 int newfds = rights->m_len / sizeof (int);
562 register int i;
563 register struct file **rp = mtod(rights, struct file **);
564 register struct file *fp;
565 int f;
566
567 if (newfds > ufavail()) {
568 for (i = 0; i < newfds; i++) {
569 fp = *rp;
570 unp_discard(fp);
571 *rp++ = 0;
572 }
573 return (EMSGSIZE);
574 }
575 for (i = 0; i < newfds; i++) {
576 f = ufalloc(0);
577 if (f < 0)
578 panic("unp_externalize");
579 fp = *rp;
580 u.u_ofile[f] = fp;
581 fp->f_msgcount--;
6c0894dd 582 unp_rights--;
bb3b4851 583 *(int *)rp++ = f;
88a7a62a
SL
584 }
585 return (0);
586}
587
588unp_internalize(rights)
589 struct mbuf *rights;
590{
591 register struct file **rp;
592 int oldfds = rights->m_len / sizeof (int);
593 register int i;
594 register struct file *fp;
595
596 rp = mtod(rights, struct file **);
44eb2da3 597 for (i = 0; i < oldfds; i++)
88a7a62a
SL
598 if (getf(*(int *)rp++) == 0)
599 return (EBADF);
600 rp = mtod(rights, struct file **);
44eb2da3 601 for (i = 0; i < oldfds; i++) {
88a7a62a
SL
602 fp = getf(*(int *)rp);
603 *rp++ = fp;
604 fp->f_count++;
605 fp->f_msgcount++;
6c0894dd 606 unp_rights++;
88a7a62a
SL
607 }
608 return (0);
609}
610
611int unp_defer, unp_gcing;
612int unp_mark();
261a8548 613extern struct domain unixdomain;
88a7a62a
SL
614
615unp_gc()
616{
617 register struct file *fp;
618 register struct socket *so;
619
620 if (unp_gcing)
621 return;
622 unp_gcing = 1;
623restart:
624 unp_defer = 0;
625 for (fp = file; fp < fileNFILE; fp++)
626 fp->f_flag &= ~(FMARK|FDEFER);
627 do {
628 for (fp = file; fp < fileNFILE; fp++) {
629 if (fp->f_count == 0)
630 continue;
631 if (fp->f_flag & FDEFER) {
632 fp->f_flag &= ~FDEFER;
633 unp_defer--;
634 } else {
635 if (fp->f_flag & FMARK)
636 continue;
637 if (fp->f_count == fp->f_msgcount)
638 continue;
639 fp->f_flag |= FMARK;
640 }
aa5945aa
MK
641 if (fp->f_type != DTYPE_SOCKET ||
642 (so = (struct socket *)fp->f_data) == 0)
88a7a62a 643 continue;
261a8548 644 if (so->so_proto->pr_domain != &unixdomain ||
c5935bca 645 (so->so_proto->pr_flags&PR_RIGHTS) == 0)
88a7a62a
SL
646 continue;
647 if (so->so_rcv.sb_flags & SB_LOCK) {
648 sbwait(&so->so_rcv);
649 goto restart;
650 }
651 unp_scan(so->so_rcv.sb_mb, unp_mark);
652 }
653 } while (unp_defer);
654 for (fp = file; fp < fileNFILE; fp++) {
655 if (fp->f_count == 0)
656 continue;
6c0894dd
MK
657 if (fp->f_count == fp->f_msgcount && (fp->f_flag & FMARK) == 0)
658 while (fp->f_msgcount)
659 unp_discard(fp);
88a7a62a
SL
660 }
661 unp_gcing = 0;
662}
663
261a8548
MK
664unp_dispose(m)
665 struct mbuf *m;
666{
667 int unp_discard();
668
148703ec
MK
669 if (m)
670 unp_scan(m, unp_discard);
261a8548
MK
671}
672
673unp_scan(m0, op)
674 register struct mbuf *m0;
88a7a62a
SL
675 int (*op)();
676{
261a8548 677 register struct mbuf *m;
88a7a62a
SL
678 register struct file **rp;
679 register int i;
148703ec 680 int qfds;
261a8548
MK
681
682 while (m0) {
683 for (m = m0; m; m = m->m_next)
684 if (m->m_type == MT_RIGHTS && m->m_len) {
685 qfds = m->m_len / sizeof (struct file *);
686 rp = mtod(m, struct file **);
687 for (i = 0; i < qfds; i++)
688 (*op)(*rp++);
689 break; /* XXX, but saves time */
690 }
148703ec 691 m0 = m0->m_act;
88a7a62a 692 }
88a7a62a
SL
693}
694
695unp_mark(fp)
696 struct file *fp;
697{
698
699 if (fp->f_flag & FMARK)
700 return;
701 unp_defer++;
702 fp->f_flag |= (FMARK|FDEFER);
703}
704
705unp_discard(fp)
706 struct file *fp;
707{
708
709 fp->f_msgcount--;
6c0894dd 710 unp_rights--;
44eb2da3 711 closef(fp);
88a7a62a 712}