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