date and time created 88/12/14 15:30:11 by sklower
[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 */
8ecea7bc 42struct sockaddr 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)
442 unp3->unp_addr = m_copy(unp2->unp_addr, 0, M_COPYALL);
443 so2 = so3;
5a48956d 444 }
d97afdcc 445 error = unp_connect2(so, so2);
88a7a62a
SL
446bad:
447 iput(ip);
448 return (error);
449}
450
d97afdcc 451unp_connect2(so, so2)
88a7a62a 452 register struct socket *so;
88a7a62a
SL
453 register struct socket *so2;
454{
455 register struct unpcb *unp = sotounpcb(so);
456 register struct unpcb *unp2;
457
458 if (so2->so_type != so->so_type)
459 return (EPROTOTYPE);
ccffacbd
SL
460 unp2 = sotounpcb(so2);
461 unp->unp_conn = unp2;
d6213d15
BJ
462 switch (so->so_type) {
463
464 case SOCK_DGRAM:
d6213d15
BJ
465 unp->unp_nextref = unp2->unp_refs;
466 unp2->unp_refs = unp;
9c40f33e 467 soisconnected(so);
d6213d15
BJ
468 break;
469
470 case SOCK_STREAM:
4f083fd7 471 unp2->unp_conn = unp;
ccffacbd
SL
472 soisconnected(so2);
473 soisconnected(so);
d6213d15
BJ
474 break;
475
476 default:
88a7a62a 477 panic("unp_connect2");
d6213d15 478 }
d6213d15 479 return (0);
d6213d15 480}
4f083fd7
SL
481
482unp_disconnect(unp)
483 struct unpcb *unp;
484{
485 register struct unpcb *unp2 = unp->unp_conn;
486
487 if (unp2 == 0)
488 return;
489 unp->unp_conn = 0;
4f083fd7
SL
490 switch (unp->unp_socket->so_type) {
491
492 case SOCK_DGRAM:
493 if (unp2->unp_refs == unp)
494 unp2->unp_refs = unp->unp_nextref;
495 else {
496 unp2 = unp2->unp_refs;
497 for (;;) {
498 if (unp2 == 0)
499 panic("unp_disconnect");
500 if (unp2->unp_nextref == unp)
501 break;
502 unp2 = unp2->unp_nextref;
503 }
504 unp2->unp_nextref = unp->unp_nextref;
505 }
506 unp->unp_nextref = 0;
c5935bca 507 unp->unp_socket->so_state &= ~SS_ISCONNECTED;
4f083fd7
SL
508 break;
509
510 case SOCK_STREAM:
ccffacbd 511 soisdisconnected(unp->unp_socket);
4f083fd7
SL
512 unp2->unp_conn = 0;
513 soisdisconnected(unp2->unp_socket);
4f083fd7
SL
514 break;
515 }
516}
517
88a7a62a 518#ifdef notdef
4f083fd7
SL
519unp_abort(unp)
520 struct unpcb *unp;
521{
522
523 unp_detach(unp);
524}
88a7a62a 525#endif
4f083fd7
SL
526
527/*ARGSUSED*/
528unp_usrclosed(unp)
529 struct unpcb *unp;
530{
531
532}
533
534unp_drop(unp, errno)
535 struct unpcb *unp;
536 int errno;
537{
d12671e0 538 struct socket *so = unp->unp_socket;
4f083fd7 539
d12671e0 540 so->so_error = errno;
4f083fd7 541 unp_disconnect(unp);
d12671e0
MK
542 if (so->so_head) {
543 so->so_pcb = (caddr_t) 0;
6c0894dd 544 m_freem(unp->unp_addr);
d12671e0
MK
545 (void) m_free(dtom(unp));
546 sofree(so);
547 }
4f083fd7
SL
548}
549
88a7a62a 550#ifdef notdef
4f083fd7
SL
551unp_drain()
552{
553
554}
88a7a62a
SL
555#endif
556
557unp_externalize(rights)
558 struct mbuf *rights;
559{
560 int newfds = rights->m_len / sizeof (int);
561 register int i;
562 register struct file **rp = mtod(rights, struct file **);
563 register struct file *fp;
564 int f;
565
566 if (newfds > ufavail()) {
567 for (i = 0; i < newfds; i++) {
568 fp = *rp;
569 unp_discard(fp);
570 *rp++ = 0;
571 }
572 return (EMSGSIZE);
573 }
574 for (i = 0; i < newfds; i++) {
575 f = ufalloc(0);
576 if (f < 0)
577 panic("unp_externalize");
578 fp = *rp;
579 u.u_ofile[f] = fp;
580 fp->f_msgcount--;
6c0894dd 581 unp_rights--;
bb3b4851 582 *(int *)rp++ = f;
88a7a62a
SL
583 }
584 return (0);
585}
586
587unp_internalize(rights)
588 struct mbuf *rights;
589{
590 register struct file **rp;
591 int oldfds = rights->m_len / sizeof (int);
592 register int i;
593 register struct file *fp;
594
595 rp = mtod(rights, struct file **);
44eb2da3 596 for (i = 0; i < oldfds; i++)
88a7a62a
SL
597 if (getf(*(int *)rp++) == 0)
598 return (EBADF);
599 rp = mtod(rights, struct file **);
44eb2da3 600 for (i = 0; i < oldfds; i++) {
88a7a62a
SL
601 fp = getf(*(int *)rp);
602 *rp++ = fp;
603 fp->f_count++;
604 fp->f_msgcount++;
6c0894dd 605 unp_rights++;
88a7a62a
SL
606 }
607 return (0);
608}
609
610int unp_defer, unp_gcing;
611int unp_mark();
261a8548 612extern struct domain unixdomain;
88a7a62a
SL
613
614unp_gc()
615{
616 register struct file *fp;
617 register struct socket *so;
618
619 if (unp_gcing)
620 return;
621 unp_gcing = 1;
622restart:
623 unp_defer = 0;
624 for (fp = file; fp < fileNFILE; fp++)
625 fp->f_flag &= ~(FMARK|FDEFER);
626 do {
627 for (fp = file; fp < fileNFILE; fp++) {
628 if (fp->f_count == 0)
629 continue;
630 if (fp->f_flag & FDEFER) {
631 fp->f_flag &= ~FDEFER;
632 unp_defer--;
633 } else {
634 if (fp->f_flag & FMARK)
635 continue;
636 if (fp->f_count == fp->f_msgcount)
637 continue;
638 fp->f_flag |= FMARK;
639 }
aa5945aa
MK
640 if (fp->f_type != DTYPE_SOCKET ||
641 (so = (struct socket *)fp->f_data) == 0)
88a7a62a 642 continue;
261a8548 643 if (so->so_proto->pr_domain != &unixdomain ||
c5935bca 644 (so->so_proto->pr_flags&PR_RIGHTS) == 0)
88a7a62a
SL
645 continue;
646 if (so->so_rcv.sb_flags & SB_LOCK) {
647 sbwait(&so->so_rcv);
648 goto restart;
649 }
650 unp_scan(so->so_rcv.sb_mb, unp_mark);
651 }
652 } while (unp_defer);
653 for (fp = file; fp < fileNFILE; fp++) {
654 if (fp->f_count == 0)
655 continue;
6c0894dd
MK
656 if (fp->f_count == fp->f_msgcount && (fp->f_flag & FMARK) == 0)
657 while (fp->f_msgcount)
658 unp_discard(fp);
88a7a62a
SL
659 }
660 unp_gcing = 0;
661}
662
261a8548
MK
663unp_dispose(m)
664 struct mbuf *m;
665{
666 int unp_discard();
667
148703ec
MK
668 if (m)
669 unp_scan(m, unp_discard);
261a8548
MK
670}
671
672unp_scan(m0, op)
673 register struct mbuf *m0;
88a7a62a
SL
674 int (*op)();
675{
261a8548 676 register struct mbuf *m;
88a7a62a
SL
677 register struct file **rp;
678 register int i;
148703ec 679 int qfds;
261a8548
MK
680
681 while (m0) {
682 for (m = m0; m; m = m->m_next)
683 if (m->m_type == MT_RIGHTS && m->m_len) {
684 qfds = m->m_len / sizeof (struct file *);
685 rp = mtod(m, struct file **);
686 for (i = 0; i < qfds; i++)
687 (*op)(*rp++);
688 break; /* XXX, but saves time */
689 }
148703ec 690 m0 = m0->m_act;
88a7a62a 691 }
88a7a62a
SL
692}
693
694unp_mark(fp)
695 struct file *fp;
696{
697
698 if (fp->f_flag & FMARK)
699 return;
700 unp_defer++;
701 fp->f_flag |= (FMARK|FDEFER);
702}
703
704unp_discard(fp)
705 struct file *fp;
706{
707
708 fp->f_msgcount--;
6c0894dd 709 unp_rights--;
44eb2da3 710 closef(fp);
88a7a62a 711}