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