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