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