xref: /csrg-svn/sys/kern/uipc_usrreq.c (revision 23524)
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.15 (Berkeley) 06/17/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 				} else
165 					error = ENOBUFS;
166 			}
167 			/* END XXX */
168 			if (nam)
169 				unp_disconnect(unp);
170 			break;
171 
172 		case SOCK_STREAM:
173 #define	rcv (&so2->so_rcv)
174 #define	snd (&so->so_snd)
175 			if (rights && rights->m_len) {
176 				error = EOPNOTSUPP;
177 				break;
178 			}
179 			if (so->so_state & SS_CANTSENDMORE) {
180 				error = EPIPE;
181 				break;
182 			}
183 			if (unp->unp_conn == 0)
184 				panic("uipc 3");
185 			so2 = unp->unp_conn->unp_socket;
186 			/*
187 			 * Send to paired receive port, and then
188 			 * give it enough resources to hold what it already has.
189 			 * Wake up readers.
190 			 */
191 			sbappend(rcv, m);
192 			snd->sb_mbmax -= rcv->sb_mbcnt - rcv->sb_mbmax;
193 			rcv->sb_mbmax = rcv->sb_mbcnt;
194 			snd->sb_hiwat -= rcv->sb_cc - rcv->sb_hiwat;
195 			rcv->sb_hiwat = rcv->sb_cc;
196 			sorwakeup(so2);
197 			m = 0;
198 #undef snd
199 #undef rcv
200 			break;
201 
202 		default:
203 			panic("uipc 4");
204 		}
205 		break;
206 
207 	case PRU_ABORT:
208 		unp_drop(unp, ECONNABORTED);
209 		break;
210 
211 /* SOME AS YET UNIMPLEMENTED HOOKS */
212 	case PRU_CONTROL:
213 		return (EOPNOTSUPP);
214 
215 /* END UNIMPLEMENTED HOOKS */
216 	case PRU_SENSE:
217 		((struct stat *) m)->st_blksize = so->so_snd.sb_hiwat;
218 		if (so->so_type == SOCK_STREAM && unp->unp_conn != 0) {
219 			so2 = unp->unp_conn->unp_socket;
220 			((struct stat *) m)->st_blksize += so2->so_rcv.sb_cc;
221 		}
222 		((struct stat *) m)->st_dev = NODEV;
223 		((struct stat *) m)->st_ino = unp_ino++;
224 		return (0);
225 
226 	case PRU_RCVOOB:
227 		return (EOPNOTSUPP);
228 
229 	case PRU_SENDOOB:
230 		error = EOPNOTSUPP;
231 		break;
232 
233 	case PRU_SOCKADDR:
234 		break;
235 
236 	case PRU_PEERADDR:
237 		break;
238 
239 	case PRU_SLOWTIMO:
240 		break;
241 
242 	default:
243 		panic("piusrreq");
244 	}
245 release:
246 	if (m)
247 		m_freem(m);
248 	return (error);
249 }
250 
251 /*
252  * We assign all buffering for stream sockets to the source,
253  * as that is where the flow control is implemented.
254  * Datagram sockets really use the sendspace as the maximum datagram size,
255  * and don't really want to reserve the sendspace.  Their recvspace should
256  * be large enough for at least one max-size datagram plus address.
257  */
258 #define	PIPSIZ	4096
259 int	unpst_sendspace = PIPSIZ;
260 int	unpst_recvspace = 0;
261 int	unpdg_sendspace = 2*1024;	/* really max datagram size */
262 int	unpdg_recvspace = 4*1024;
263 
264 unp_attach(so)
265 	struct socket *so;
266 {
267 	register struct mbuf *m;
268 	register struct unpcb *unp;
269 	int error;
270 
271 	switch (so->so_type) {
272 
273 	case SOCK_STREAM:
274 		error = soreserve(so, unpst_sendspace, unpst_recvspace);
275 		break;
276 
277 	case SOCK_DGRAM:
278 		error = soreserve(so, unpdg_sendspace, unpdg_recvspace);
279 		break;
280 	}
281 	if (error)
282 		return (error);
283 	m = m_getclr(M_DONTWAIT, MT_PCB);
284 	if (m == NULL)
285 		return (ENOBUFS);
286 	unp = mtod(m, struct unpcb *);
287 	so->so_pcb = (caddr_t)unp;
288 	unp->unp_socket = so;
289 	return (0);
290 }
291 
292 unp_detach(unp)
293 	register struct unpcb *unp;
294 {
295 
296 	if (unp->unp_inode) {
297 		unp->unp_inode->i_socket = 0;
298 		irele(unp->unp_inode);
299 		unp->unp_inode = 0;
300 	}
301 	if (unp->unp_conn)
302 		unp_disconnect(unp);
303 	while (unp->unp_refs)
304 		unp_drop(unp->unp_refs, ECONNRESET);
305 	soisdisconnected(unp->unp_socket);
306 	unp->unp_socket->so_pcb = 0;
307 	m_freem(unp->unp_remaddr);
308 	(void) m_free(dtom(unp));
309 }
310 
311 unp_bind(unp, nam)
312 	struct unpcb *unp;
313 	struct mbuf *nam;
314 {
315 	struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *);
316 	register struct inode *ip;
317 	register struct nameidata *ndp = &u.u_nd;
318 	int error;
319 
320 	ndp->ni_dirp = soun->sun_path;
321 	if (nam->m_len == MLEN)
322 		return (EINVAL);
323 	*(mtod(nam, caddr_t) + nam->m_len) = 0;
324 /* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */
325 	ndp->ni_nameiop = CREATE | FOLLOW;
326 	ndp->ni_segflg = UIO_SYSSPACE;
327 	ip = namei(ndp);
328 	if (ip) {
329 		iput(ip);
330 		return (EADDRINUSE);
331 	}
332 	if (error = u.u_error) {
333 		u.u_error = 0;			/* XXX */
334 		return (error);
335 	}
336 	ip = maknode(IFSOCK | 0777, ndp);
337 	if (ip == NULL) {
338 		error = u.u_error;		/* XXX */
339 		u.u_error = 0;			/* XXX */
340 		return (error);
341 	}
342 	ip->i_socket = unp->unp_socket;
343 	unp->unp_inode = ip;
344 	iunlock(ip);			/* but keep reference */
345 	return (0);
346 }
347 
348 unp_connect(so, nam)
349 	struct socket *so;
350 	struct mbuf *nam;
351 {
352 	register struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *);
353 	register struct inode *ip;
354 	int error;
355 	register struct socket *so2;
356 	register struct nameidata *ndp = &u.u_nd;
357 
358 	ndp->ni_dirp = soun->sun_path;
359 	if (nam->m_len + (nam->m_off - MMINOFF) == MLEN)
360 		return (EMSGSIZE);
361 	*(mtod(nam, caddr_t) + nam->m_len) = 0;
362 	ndp->ni_nameiop = LOOKUP | FOLLOW;
363 	ndp->ni_segflg = UIO_SYSSPACE;
364 	ip = namei(ndp);
365 	if (ip == 0) {
366 		error = u.u_error;
367 		u.u_error = 0;
368 		return (error);		/* XXX */
369 	}
370 	if (access(ip, IWRITE)) {
371 		error = u.u_error;
372 		u.u_error = 0; 		/* XXX */
373 		goto bad;
374 	}
375 	if ((ip->i_mode&IFMT) != IFSOCK) {
376 		error = ENOTSOCK;
377 		goto bad;
378 	}
379 	so2 = ip->i_socket;
380 	if (so2 == 0) {
381 		error = ECONNREFUSED;
382 		goto bad;
383 	}
384 	if (so->so_type != so2->so_type) {
385 		error = EPROTOTYPE;
386 		goto bad;
387 	}
388 	if (so->so_proto->pr_flags & PR_CONNREQUIRED &&
389 	    ((so2->so_options&SO_ACCEPTCONN) == 0 ||
390 	     (so2 = sonewconn(so2)) == 0)) {
391 		error = ECONNREFUSED;
392 		goto bad;
393 	}
394 	error = unp_connect2(so, nam, so2);
395 bad:
396 	iput(ip);
397 	return (error);
398 }
399 
400 unp_connect2(so, sonam, so2)
401 	register struct socket *so;
402 	struct mbuf *sonam;
403 	register struct socket *so2;
404 {
405 	register struct unpcb *unp = sotounpcb(so);
406 	register struct unpcb *unp2;
407 
408 	if (so2->so_type != so->so_type)
409 		return (EPROTOTYPE);
410 	unp2 = sotounpcb(so2);
411 	unp->unp_conn = unp2;
412 	switch (so->so_type) {
413 
414 	case SOCK_DGRAM:
415 		unp->unp_nextref = unp2->unp_refs;
416 		unp2->unp_refs = unp;
417 		soisconnected(so);
418 		break;
419 
420 	case SOCK_STREAM:
421 		unp2->unp_conn = unp;
422 		if (sonam)
423 			unp2->unp_remaddr = m_copy(sonam, 0, (int)M_COPYALL);
424 		soisconnected(so2);
425 		soisconnected(so);
426 		break;
427 
428 	default:
429 		panic("unp_connect2");
430 	}
431 	return (0);
432 }
433 
434 unp_disconnect(unp)
435 	struct unpcb *unp;
436 {
437 	register struct unpcb *unp2 = unp->unp_conn;
438 
439 	if (unp2 == 0)
440 		return;
441 	unp->unp_conn = 0;
442 	switch (unp->unp_socket->so_type) {
443 
444 	case SOCK_DGRAM:
445 		if (unp2->unp_refs == unp)
446 			unp2->unp_refs = unp->unp_nextref;
447 		else {
448 			unp2 = unp2->unp_refs;
449 			for (;;) {
450 				if (unp2 == 0)
451 					panic("unp_disconnect");
452 				if (unp2->unp_nextref == unp)
453 					break;
454 				unp2 = unp2->unp_nextref;
455 			}
456 			unp2->unp_nextref = unp->unp_nextref;
457 		}
458 		unp->unp_nextref = 0;
459 		unp->unp_socket->so_state &= ~SS_ISCONNECTED;
460 		break;
461 
462 	case SOCK_STREAM:
463 		soisdisconnected(unp->unp_socket);
464 		unp2->unp_conn = 0;
465 		soisdisconnected(unp2->unp_socket);
466 		break;
467 	}
468 }
469 
470 #ifdef notdef
471 unp_abort(unp)
472 	struct unpcb *unp;
473 {
474 
475 	unp_detach(unp);
476 }
477 #endif
478 
479 /*ARGSUSED*/
480 unp_usrclosed(unp)
481 	struct unpcb *unp;
482 {
483 
484 }
485 
486 unp_drop(unp, errno)
487 	struct unpcb *unp;
488 	int errno;
489 {
490 	struct socket *so = unp->unp_socket;
491 
492 	so->so_error = errno;
493 	unp_disconnect(unp);
494 	if (so->so_head) {
495 		so->so_pcb = (caddr_t) 0;
496 		m_freem(unp->unp_remaddr);
497 		(void) m_free(dtom(unp));
498 		sofree(so);
499 	}
500 }
501 
502 #ifdef notdef
503 unp_drain()
504 {
505 
506 }
507 #endif
508 
509 unp_externalize(rights)
510 	struct mbuf *rights;
511 {
512 	int newfds = rights->m_len / sizeof (int);
513 	register int i;
514 	register struct file **rp = mtod(rights, struct file **);
515 	register struct file *fp;
516 	int f;
517 
518 	if (newfds > ufavail()) {
519 		for (i = 0; i < newfds; i++) {
520 			fp = *rp;
521 			unp_discard(fp);
522 			*rp++ = 0;
523 		}
524 		return (EMSGSIZE);
525 	}
526 	for (i = 0; i < newfds; i++) {
527 		f = ufalloc(0);
528 		if (f < 0)
529 			panic("unp_externalize");
530 		fp = *rp;
531 		u.u_ofile[f] = fp;
532 		fp->f_msgcount--;
533 		*(int *)rp++ = f;
534 	}
535 	return (0);
536 }
537 
538 unp_internalize(rights)
539 	struct mbuf *rights;
540 {
541 	register struct file **rp;
542 	int oldfds = rights->m_len / sizeof (int);
543 	register int i;
544 	register struct file *fp;
545 
546 	rp = mtod(rights, struct file **);
547 	for (i = 0; i < oldfds; i++)
548 		if (getf(*(int *)rp++) == 0)
549 			return (EBADF);
550 	rp = mtod(rights, struct file **);
551 	for (i = 0; i < oldfds; i++) {
552 		fp = getf(*(int *)rp);
553 		*rp++ = fp;
554 		fp->f_count++;
555 		fp->f_msgcount++;
556 	}
557 	return (0);
558 }
559 
560 int	unp_defer, unp_gcing;
561 int	unp_mark();
562 extern	struct domain unixdomain;
563 
564 unp_gc()
565 {
566 	register struct file *fp;
567 	register struct socket *so;
568 
569 	if (unp_gcing)
570 		return;
571 	unp_gcing = 1;
572 restart:
573 	unp_defer = 0;
574 	for (fp = file; fp < fileNFILE; fp++)
575 		fp->f_flag &= ~(FMARK|FDEFER);
576 	do {
577 		for (fp = file; fp < fileNFILE; fp++) {
578 			if (fp->f_count == 0)
579 				continue;
580 			if (fp->f_flag & FDEFER) {
581 				fp->f_flag &= ~FDEFER;
582 				unp_defer--;
583 			} else {
584 				if (fp->f_flag & FMARK)
585 					continue;
586 				if (fp->f_count == fp->f_msgcount)
587 					continue;
588 				fp->f_flag |= FMARK;
589 			}
590 			if (fp->f_type != DTYPE_SOCKET)
591 				continue;
592 			so = (struct socket *)fp->f_data;
593 			if (so->so_proto->pr_domain != &unixdomain ||
594 			    (so->so_proto->pr_flags&PR_RIGHTS) == 0)
595 				continue;
596 			if (so->so_rcv.sb_flags & SB_LOCK) {
597 				sbwait(&so->so_rcv);
598 				goto restart;
599 			}
600 			unp_scan(so->so_rcv.sb_mb, unp_mark);
601 		}
602 	} while (unp_defer);
603 	for (fp = file; fp < fileNFILE; fp++) {
604 		if (fp->f_count == 0)
605 			continue;
606 		if (fp->f_count == fp->f_msgcount && (fp->f_flag&FMARK)==0) {
607 			if (fp->f_type != DTYPE_SOCKET)
608 				panic("unp_gc");
609 			(void) soshutdown((struct socket *)fp->f_data, 0);
610 		}
611 	}
612 	unp_gcing = 0;
613 }
614 
615 unp_dispose(m)
616 	struct mbuf *m;
617 {
618 	int unp_discard();
619 
620 	if (m)
621 		unp_scan(m, unp_discard);
622 }
623 
624 unp_scan(m0, op)
625 	register struct mbuf *m0;
626 	int (*op)();
627 {
628 	register struct mbuf *m;
629 	register struct file **rp;
630 	register int i;
631 	int qfds;
632 
633 	while (m0) {
634 		for (m = m0; m; m = m->m_next)
635 			if (m->m_type == MT_RIGHTS && m->m_len) {
636 				qfds = m->m_len / sizeof (struct file *);
637 				rp = mtod(m, struct file **);
638 				for (i = 0; i < qfds; i++)
639 					(*op)(*rp++);
640 				break;		/* XXX, but saves time */
641 			}
642 		m0 = m0->m_act;
643 	}
644 }
645 
646 unp_mark(fp)
647 	struct file *fp;
648 {
649 
650 	if (fp->f_flag & FMARK)
651 		return;
652 	unp_defer++;
653 	fp->f_flag |= (FMARK|FDEFER);
654 }
655 
656 unp_discard(fp)
657 	struct file *fp;
658 {
659 
660 	fp->f_msgcount--;
661 	closef(fp);
662 }
663