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