remove getlogin.3
[unix-history] / usr / src / sys / kern / uipc_usrreq.c
CommitLineData
da7c5cc6 1/*
96e6449f 2 *
dbf0c423 3 * %sccs.include.redist.c%
f1ff9444 4 *
dbf0c423 5 * @(#)uipc_usrreq.c 7.20 (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);
105 unp_usrclosed(unp);
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
MK
192 if (control) {
193 (void)sbappendcontrol(rcv, m, control);
194 control = 0;
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
SL
512
513/*ARGSUSED*/
514unp_usrclosed(unp)
515 struct unpcb *unp;
516{
517
518}
519
520unp_drop(unp, errno)
521 struct unpcb *unp;
522 int errno;
523{
d12671e0 524 struct socket *so = unp->unp_socket;
4f083fd7 525
d12671e0 526 so->so_error = errno;
4f083fd7 527 unp_disconnect(unp);
d12671e0
MK
528 if (so->so_head) {
529 so->so_pcb = (caddr_t) 0;
6c0894dd 530 m_freem(unp->unp_addr);
d12671e0
MK
531 (void) m_free(dtom(unp));
532 sofree(so);
533 }
4f083fd7
SL
534}
535
88a7a62a 536#ifdef notdef
4f083fd7
SL
537unp_drain()
538{
539
540}
88a7a62a
SL
541#endif
542
543unp_externalize(rights)
544 struct mbuf *rights;
545{
88a7a62a 546 register int i;
0293c204
KS
547 register struct cmsghdr *cm = mtod(rights, struct cmsghdr *);
548 register struct file **rp = (struct file **)(cm + 1);
88a7a62a 549 register struct file *fp;
0293c204 550 int newfds = (cm->cmsg_len - sizeof(*cm)) / sizeof (int);
88a7a62a
SL
551 int f;
552
553 if (newfds > ufavail()) {
554 for (i = 0; i < newfds; i++) {
555 fp = *rp;
556 unp_discard(fp);
557 *rp++ = 0;
558 }
559 return (EMSGSIZE);
560 }
561 for (i = 0; i < newfds; i++) {
f1ff9444 562 if (ufalloc(0, &f))
88a7a62a
SL
563 panic("unp_externalize");
564 fp = *rp;
565 u.u_ofile[f] = fp;
566 fp->f_msgcount--;
6c0894dd 567 unp_rights--;
bb3b4851 568 *(int *)rp++ = f;
88a7a62a
SL
569 }
570 return (0);
571}
572
d83a7d17
MK
573unp_internalize(control)
574 struct mbuf *control;
88a7a62a 575{
d83a7d17 576 register struct cmsghdr *cm = mtod(control, struct cmsghdr *);
88a7a62a 577 register struct file **rp;
88a7a62a 578 register struct file *fp;
d83a7d17
MK
579 register int i, fd;
580 int oldfds;
88a7a62a 581
d83a7d17
MK
582 if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET ||
583 cm->cmsg_len != control->m_len)
0293c204
KS
584 return (EINVAL);
585 oldfds = (cm->cmsg_len - sizeof (*cm)) / sizeof (int);
0293c204 586 rp = (struct file **)(cm + 1);
c4ec2128
KM
587 for (i = 0; i < oldfds; i++) {
588 fd = *(int *)rp++;
589 if ((unsigned)fd >= NOFILE || u.u_ofile[fd] == NULL)
88a7a62a 590 return (EBADF);
c4ec2128 591 }
0293c204 592 rp = (struct file **)(cm + 1);
44eb2da3 593 for (i = 0; i < oldfds; i++) {
c4ec2128 594 fp = u.u_ofile[*(int *)rp];
88a7a62a
SL
595 *rp++ = fp;
596 fp->f_count++;
597 fp->f_msgcount++;
6c0894dd 598 unp_rights++;
88a7a62a
SL
599 }
600 return (0);
601}
602
603int unp_defer, unp_gcing;
604int unp_mark();
261a8548 605extern struct domain unixdomain;
88a7a62a
SL
606
607unp_gc()
608{
609 register struct file *fp;
610 register struct socket *so;
611
612 if (unp_gcing)
613 return;
614 unp_gcing = 1;
615restart:
616 unp_defer = 0;
617 for (fp = file; fp < fileNFILE; fp++)
618 fp->f_flag &= ~(FMARK|FDEFER);
619 do {
620 for (fp = file; fp < fileNFILE; fp++) {
621 if (fp->f_count == 0)
622 continue;
623 if (fp->f_flag & FDEFER) {
624 fp->f_flag &= ~FDEFER;
625 unp_defer--;
626 } else {
627 if (fp->f_flag & FMARK)
628 continue;
629 if (fp->f_count == fp->f_msgcount)
630 continue;
631 fp->f_flag |= FMARK;
632 }
aa5945aa
MK
633 if (fp->f_type != DTYPE_SOCKET ||
634 (so = (struct socket *)fp->f_data) == 0)
88a7a62a 635 continue;
261a8548 636 if (so->so_proto->pr_domain != &unixdomain ||
c5935bca 637 (so->so_proto->pr_flags&PR_RIGHTS) == 0)
88a7a62a
SL
638 continue;
639 if (so->so_rcv.sb_flags & SB_LOCK) {
640 sbwait(&so->so_rcv);
641 goto restart;
642 }
643 unp_scan(so->so_rcv.sb_mb, unp_mark);
644 }
645 } while (unp_defer);
646 for (fp = file; fp < fileNFILE; fp++) {
647 if (fp->f_count == 0)
648 continue;
6c0894dd
MK
649 if (fp->f_count == fp->f_msgcount && (fp->f_flag & FMARK) == 0)
650 while (fp->f_msgcount)
651 unp_discard(fp);
88a7a62a
SL
652 }
653 unp_gcing = 0;
654}
655
261a8548
MK
656unp_dispose(m)
657 struct mbuf *m;
658{
659 int unp_discard();
660
148703ec
MK
661 if (m)
662 unp_scan(m, unp_discard);
261a8548
MK
663}
664
665unp_scan(m0, op)
666 register struct mbuf *m0;
88a7a62a
SL
667 int (*op)();
668{
261a8548 669 register struct mbuf *m;
88a7a62a 670 register struct file **rp;
d83a7d17 671 register struct cmsghdr *cm;
88a7a62a 672 register int i;
148703ec 673 int qfds;
261a8548
MK
674
675 while (m0) {
676 for (m = m0; m; m = m->m_next)
d83a7d17
MK
677 if (m->m_type == MT_CONTROL &&
678 m->m_len >= sizeof(*cm)) {
0293c204 679 cm = mtod(m, struct cmsghdr *);
d83a7d17
MK
680 if (cm->cmsg_level != SOL_SOCKET ||
681 cm->cmsg_type != SCM_RIGHTS)
682 continue;
0293c204
KS
683 qfds = (cm->cmsg_len - sizeof *cm)
684 / sizeof (struct file *);
685 rp = (struct file **)(cm + 1);
261a8548
MK
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--;
69be5b7a 710 (void) closef(fp);
88a7a62a 711}