|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution is only permitted until one year after the first shipment
6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
7: * binary forms are permitted provided that: (1) source distributions retain
8: * this entire copyright notice and comment, and (2) distributions including
9: * binaries display the following acknowledgement: This product includes
10: * software developed by the University of California, Berkeley and its
11: * contributors'' in the documentation or other materials provided with the
12: * distribution and in all advertising materials mentioning features or use
13: * of this software. Neither the name of the University nor the names of
14: * its contributors may be used to endorse or promote products derived from
15: * this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: * @(#)uipc_usrreq.c 7.21 (Berkeley) 7/27/90
21: */
22:
23: #include "param.h"
24: #include "user.h"
25: #include "domain.h"
26: #include "protosw.h"
27: #include "socket.h"
28: #include "socketvar.h"
29: #include "unpcb.h"
30: #include "un.h"
31: #include "vnode.h"
32: #include "file.h"
33: #include "stat.h"
34: #include "mbuf.h"
35:
36: /*
37: * Unix communications domain.
38: *
39: * TODO:
40: * SEQPACKET, RDM
41: * rethink name space problems
42: * need a proper out-of-band
43: */
44: struct sockaddr sun_noname = { sizeof(sun_noname), AF_UNIX };
45: ino_t unp_ino; /* prototype for fake inode numbers */
46:
47: /*ARGSUSED*/
48: uipc_usrreq(so, req, m, nam, control)
49: struct socket *so;
50: int req;
51: struct mbuf *m, *nam, *control;
52: {
53: struct unpcb *unp = sotounpcb(so);
54: register struct socket *so2;
55: register int error = 0;
56:
57: if (req == PRU_CONTROL)
58: return (EOPNOTSUPP);
59: if (req != PRU_SEND && control && control->m_len) {
60: error = EOPNOTSUPP;
61: goto release;
62: }
63: if (unp == 0 && req != PRU_ATTACH) {
64: error = EINVAL;
65: goto release;
66: }
67: switch (req) {
68:
69: case PRU_ATTACH:
70: if (unp) {
71: error = EISCONN;
72: break;
73: }
74: error = unp_attach(so);
75: break;
76:
77: case PRU_DETACH:
78: unp_detach(unp);
79: break;
80:
81: case PRU_BIND:
82: error = unp_bind(unp, nam);
83: break;
84:
85: case PRU_LISTEN:
86: if (unp->unp_vnode == 0)
87: error = EINVAL;
88: break;
89:
90: case PRU_CONNECT:
91: error = unp_connect(so, nam);
92: break;
93:
94: case PRU_CONNECT2:
95: error = unp_connect2(so, (struct socket *)nam);
96: break;
97:
98: case PRU_DISCONNECT:
99: unp_disconnect(unp);
100: break;
101:
102: case PRU_ACCEPT:
103: /*
104: * Pass back name of connected socket,
105: * if it was bound and we are still connected
106: * (our peer may have closed already!).
107: */
108: if (unp->unp_conn && unp->unp_conn->unp_addr) {
109: nam->m_len = unp->unp_conn->unp_addr->m_len;
110: bcopy(mtod(unp->unp_conn->unp_addr, caddr_t),
111: mtod(nam, caddr_t), (unsigned)nam->m_len);
112: } else {
113: nam->m_len = sizeof(sun_noname);
114: *(mtod(nam, struct sockaddr *)) = sun_noname;
115: }
116: break;
117:
118: case PRU_SHUTDOWN:
119: socantsendmore(so);
120: unp_shutdown(unp);
121: break;
122:
123: case PRU_RCVD:
124: switch (so->so_type) {
125:
126: case SOCK_DGRAM:
127: panic("uipc 1");
128: /*NOTREACHED*/
129:
130: case SOCK_STREAM:
131: #define rcv (&so->so_rcv)
132: #define snd (&so2->so_snd)
133: if (unp->unp_conn == 0)
134: break;
135: so2 = unp->unp_conn->unp_socket;
136: /*
137: * Adjust backpressure on sender
138: * and wakeup any waiting to write.
139: */
140: snd->sb_mbmax += unp->unp_mbcnt - rcv->sb_mbcnt;
141: unp->unp_mbcnt = rcv->sb_mbcnt;
142: snd->sb_hiwat += unp->unp_cc - rcv->sb_cc;
143: unp->unp_cc = rcv->sb_cc;
144: sowwakeup(so2);
145: #undef snd
146: #undef rcv
147: break;
148:
149: default:
150: panic("uipc 2");
151: }
152: break;
153:
154: case PRU_SEND:
155: if (control && (error = unp_internalize(control)))
156: break;
157: switch (so->so_type) {
158:
159: case SOCK_DGRAM: {
160: struct sockaddr *from;
161:
162: if (nam) {
163: if (unp->unp_conn) {
164: error = EISCONN;
165: break;
166: }
167: error = unp_connect(so, nam);
168: if (error)
169: break;
170: } else {
171: if (unp->unp_conn == 0) {
172: error = ENOTCONN;
173: break;
174: }
175: }
176: so2 = unp->unp_conn->unp_socket;
177: if (unp->unp_addr)
178: from = mtod(unp->unp_addr, struct sockaddr *);
179: else
180: from = &sun_noname;
181: if (sbappendaddr(&so2->so_rcv, from, m, control)) {
182: sorwakeup(so2);
183: m = 0;
184: control = 0;
185: } else
186: error = ENOBUFS;
187: if (nam)
188: unp_disconnect(unp);
189: break;
190: }
191:
192: case SOCK_STREAM:
193: #define rcv (&so2->so_rcv)
194: #define snd (&so->so_snd)
195: if (so->so_state & SS_CANTSENDMORE) {
196: error = EPIPE;
197: break;
198: }
199: if (unp->unp_conn == 0)
200: panic("uipc 3");
201: so2 = unp->unp_conn->unp_socket;
202: /*
203: * Send to paired receive port, and then reduce
204: * send buffer hiwater marks to maintain backpressure.
205: * Wake up readers.
206: */
207: if (control) {
208: if (sbappendcontrol(rcv, m, control))
209: control = 0;
210: } else
211: sbappend(rcv, m);
212: snd->sb_mbmax -=
213: rcv->sb_mbcnt - unp->unp_conn->unp_mbcnt;
214: unp->unp_conn->unp_mbcnt = rcv->sb_mbcnt;
215: snd->sb_hiwat -= rcv->sb_cc - unp->unp_conn->unp_cc;
216: unp->unp_conn->unp_cc = rcv->sb_cc;
217: sorwakeup(so2);
218: m = 0;
219: #undef snd
220: #undef rcv
221: break;
222:
223: default:
224: panic("uipc 4");
225: }
226: break;
227:
228: case PRU_ABORT:
229: unp_drop(unp, ECONNABORTED);
230: break;
231:
232: case PRU_SENSE:
233: ((struct stat *) m)->st_blksize = so->so_snd.sb_hiwat;
234: if (so->so_type == SOCK_STREAM && unp->unp_conn != 0) {
235: so2 = unp->unp_conn->unp_socket;
236: ((struct stat *) m)->st_blksize += so2->so_rcv.sb_cc;
237: }
238: ((struct stat *) m)->st_dev = NODEV;
239: if (unp->unp_ino == 0)
240: unp->unp_ino = unp_ino++;
241: ((struct stat *) m)->st_ino = unp->unp_ino;
242: return (0);
243:
244: case PRU_RCVOOB:
245: return (EOPNOTSUPP);
246:
247: case PRU_SENDOOB:
248: error = EOPNOTSUPP;
249: break;
250:
251: case PRU_SOCKADDR:
252: if (unp->unp_addr) {
253: nam->m_len = unp->unp_addr->m_len;
254: bcopy(mtod(unp->unp_addr, caddr_t),
255: mtod(nam, caddr_t), (unsigned)nam->m_len);
256: } else
257: nam->m_len = 0;
258: break;
259:
260: case PRU_PEERADDR:
261: if (unp->unp_conn && unp->unp_conn->unp_addr) {
262: nam->m_len = unp->unp_conn->unp_addr->m_len;
263: bcopy(mtod(unp->unp_conn->unp_addr, caddr_t),
264: mtod(nam, caddr_t), (unsigned)nam->m_len);
265: } else
266: nam->m_len = 0;
267: break;
268:
269: case PRU_SLOWTIMO:
270: break;
271:
272: default:
273: panic("piusrreq");
274: }
275: release:
276: if (control)
277: m_freem(control);
278: if (m)
279: m_freem(m);
280: return (error);
281: }
282:
283: /*
284: * Both send and receive buffers are allocated PIPSIZ bytes of buffering
285: * for stream sockets, although the total for sender and receiver is
286: * actually only PIPSIZ.
287: * Datagram sockets really use the sendspace as the maximum datagram size,
288: * and don't really want to reserve the sendspace. Their recvspace should
289: * be large enough for at least one max-size datagram plus address.
290: */
291: #define PIPSIZ 4096
292: u_long unpst_sendspace = PIPSIZ;
293: u_long unpst_recvspace = PIPSIZ;
294: u_long unpdg_sendspace = 2*1024; /* really max datagram size */
295: u_long unpdg_recvspace = 4*1024;
296:
297: int unp_rights; /* file descriptors in flight */
298:
299: unp_attach(so)
300: struct socket *so;
301: {
302: register struct mbuf *m;
303: register struct unpcb *unp;
304: int error;
305:
306: if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
307: switch (so->so_type) {
308:
309: case SOCK_STREAM:
310: error = soreserve(so, unpst_sendspace, unpst_recvspace);
311: break;
312:
313: case SOCK_DGRAM:
314: error = soreserve(so, unpdg_sendspace, unpdg_recvspace);
315: break;
316: }
317: if (error)
318: return (error);
319: }
320: m = m_getclr(M_DONTWAIT, MT_PCB);
321: if (m == NULL)
322: return (ENOBUFS);
323: unp = mtod(m, struct unpcb *);
324: so->so_pcb = (caddr_t)unp;
325: unp->unp_socket = so;
326: return (0);
327: }
328:
329: unp_detach(unp)
330: register struct unpcb *unp;
331: {
332:
333: if (unp->unp_vnode) {
334: unp->unp_vnode->v_socket = 0;
335: vrele(unp->unp_vnode);
336: unp->unp_vnode = 0;
337: }
338: if (unp->unp_conn)
339: unp_disconnect(unp);
340: while (unp->unp_refs)
341: unp_drop(unp->unp_refs, ECONNRESET);
342: soisdisconnected(unp->unp_socket);
343: unp->unp_socket->so_pcb = 0;
344: m_freem(unp->unp_addr);
345: (void) m_free(dtom(unp));
346: if (unp_rights)
347: unp_gc();
348: }
349:
350: unp_bind(unp, nam)
351: struct unpcb *unp;
352: struct mbuf *nam;
353: {
354: struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *);
355: register struct vnode *vp;
356: register struct nameidata *ndp = &u.u_nd;
357: struct vattr vattr;
358: int error;
359:
360: ndp->ni_dirp = soun->sun_path;
361: if (unp->unp_vnode != NULL)
362: return (EINVAL);
363: if (nam->m_len == MLEN) {
364: if (*(mtod(nam, caddr_t) + nam->m_len - 1) != 0)
365: return (EINVAL);
366: } else
367: *(mtod(nam, caddr_t) + nam->m_len) = 0;
368: /* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */
369: ndp->ni_nameiop = CREATE | FOLLOW | LOCKPARENT;
370: ndp->ni_segflg = UIO_SYSSPACE;
371: if (error = namei(ndp))
372: return (error);
373: vp = ndp->ni_vp;
374: if (vp != NULL) {
375: VOP_ABORTOP(ndp);
376: if (ndp->ni_dvp == vp)
377: vrele(ndp->ni_dvp);
378: else
379: vput(ndp->ni_dvp);
380: vrele(vp);
381: return (EADDRINUSE);
382: }
383: VATTR_NULL(&vattr);
384: vattr.va_type = VSOCK;
385: vattr.va_mode = 0777;
386: if (error = VOP_CREATE(ndp, &vattr))
387: return (error);
388: vp = ndp->ni_vp;
389: vp->v_socket = unp->unp_socket;
390: unp->unp_vnode = vp;
391: unp->unp_addr = m_copy(nam, 0, (int)M_COPYALL);
392: VOP_UNLOCK(vp);
393: return (0);
394: }
395:
396: unp_connect(so, nam)
397: struct socket *so;
398: struct mbuf *nam;
399: {
400: register struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *);
401: register struct vnode *vp;
402: register struct socket *so2, *so3;
403: register struct nameidata *ndp = &u.u_nd;
404: struct unpcb *unp2, *unp3;
405: int error;
406:
407: ndp->ni_dirp = soun->sun_path;
408: if (nam->m_data + nam->m_len == &nam->m_dat[MLEN]) { /* XXX */
409: if (*(mtod(nam, caddr_t) + nam->m_len - 1) != 0)
410: return (EMSGSIZE);
411: } else
412: *(mtod(nam, caddr_t) + nam->m_len) = 0;
413: ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
414: ndp->ni_segflg = UIO_SYSSPACE;
415: if (error = namei(ndp))
416: return (error);
417: vp = ndp->ni_vp;
418: if (vp->v_type != VSOCK) {
419: error = ENOTSOCK;
420: goto bad;
421: }
422: if (error = VOP_ACCESS(vp, VWRITE, ndp->ni_cred))
423: goto bad;
424: so2 = vp->v_socket;
425: if (so2 == 0) {
426: error = ECONNREFUSED;
427: goto bad;
428: }
429: if (so->so_type != so2->so_type) {
430: error = EPROTOTYPE;
431: goto bad;
432: }
433: if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
434: if ((so2->so_options & SO_ACCEPTCONN) == 0 ||
435: (so3 = sonewconn(so2, 0)) == 0) {
436: error = ECONNREFUSED;
437: goto bad;
438: }
439: unp2 = sotounpcb(so2);
440: unp3 = sotounpcb(so3);
441: if (unp2->unp_addr)
442: unp3->unp_addr =
443: m_copy(unp2->unp_addr, 0, (int)M_COPYALL);
444: so2 = so3;
445: }
446: error = unp_connect2(so, so2);
447: bad:
448: vput(vp);
449: return (error);
450: }
451:
452: unp_connect2(so, so2)
453: register struct socket *so;
454: register struct socket *so2;
455: {
456: register struct unpcb *unp = sotounpcb(so);
457: register struct unpcb *unp2;
458:
459: if (so2->so_type != so->so_type)
460: return (EPROTOTYPE);
461: unp2 = sotounpcb(so2);
462: unp->unp_conn = unp2;
463: switch (so->so_type) {
464:
465: case SOCK_DGRAM:
466: unp->unp_nextref = unp2->unp_refs;
467: unp2->unp_refs = unp;
468: soisconnected(so);
469: break;
470:
471: case SOCK_STREAM:
472: unp2->unp_conn = unp;
473: soisconnected(so);
474: soisconnected(so2);
475: break;
476:
477: default:
478: panic("unp_connect2");
479: }
480: return (0);
481: }
482:
483: unp_disconnect(unp)
484: struct unpcb *unp;
485: {
486: register struct unpcb *unp2 = unp->unp_conn;
487:
488: if (unp2 == 0)
489: return;
490: unp->unp_conn = 0;
491: switch (unp->unp_socket->so_type) {
492:
493: case SOCK_DGRAM:
494: if (unp2->unp_refs == unp)
495: unp2->unp_refs = unp->unp_nextref;
496: else {
497: unp2 = unp2->unp_refs;
498: for (;;) {
499: if (unp2 == 0)
500: panic("unp_disconnect");
501: if (unp2->unp_nextref == unp)
502: break;
503: unp2 = unp2->unp_nextref;
504: }
505: unp2->unp_nextref = unp->unp_nextref;
506: }
507: unp->unp_nextref = 0;
508: unp->unp_socket->so_state &= ~SS_ISCONNECTED;
509: break;
510:
511: case SOCK_STREAM:
512: soisdisconnected(unp->unp_socket);
513: unp2->unp_conn = 0;
514: soisdisconnected(unp2->unp_socket);
515: break;
516: }
517: }
518:
519: #ifdef notdef
520: unp_abort(unp)
521: struct unpcb *unp;
522: {
523:
524: unp_detach(unp);
525: }
526: #endif
527:
528: unp_shutdown(unp)
529: struct unpcb *unp;
530: {
531: struct socket *so;
532:
533: if (unp->unp_socket->so_type == SOCK_STREAM && unp->unp_conn &&
534: (so = unp->unp_conn->unp_socket))
535: socantrcvmore(so);
536: }
537:
538: unp_drop(unp, errno)
539: struct unpcb *unp;
540: int errno;
541: {
542: struct socket *so = unp->unp_socket;
543:
544: so->so_error = errno;
545: unp_disconnect(unp);
546: if (so->so_head) {
547: so->so_pcb = (caddr_t) 0;
548: m_freem(unp->unp_addr);
549: (void) m_free(dtom(unp));
550: sofree(so);
551: }
552: }
553:
554: #ifdef notdef
555: unp_drain()
556: {
557:
558: }
559: #endif
560:
561: unp_externalize(rights)
562: struct mbuf *rights;
563: {
564: register int i;
565: register struct cmsghdr *cm = mtod(rights, struct cmsghdr *);
566: register struct file **rp = (struct file **)(cm + 1);
567: register struct file *fp;
568: int newfds = (cm->cmsg_len - sizeof(*cm)) / sizeof (int);
569: int f;
570:
571: if (newfds > ufavail()) {
572: for (i = 0; i < newfds; i++) {
573: fp = *rp;
574: unp_discard(fp);
575: *rp++ = 0;
576: }
577: return (EMSGSIZE);
578: }
579: for (i = 0; i < newfds; i++) {
580: if (ufalloc(0, &f))
581: panic("unp_externalize");
582: fp = *rp;
583: u.u_ofile[f] = fp;
584: fp->f_msgcount--;
585: unp_rights--;
586: *(int *)rp++ = f;
587: }
588: return (0);
589: }
590:
591: unp_internalize(control)
592: struct mbuf *control;
593: {
594: register struct cmsghdr *cm = mtod(control, struct cmsghdr *);
595: register struct file **rp;
596: register struct file *fp;
597: register int i, fd;
598: int oldfds;
599:
600: if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET ||
601: cm->cmsg_len != control->m_len)
602: return (EINVAL);
603: oldfds = (cm->cmsg_len - sizeof (*cm)) / sizeof (int);
604: rp = (struct file **)(cm + 1);
605: for (i = 0; i < oldfds; i++) {
606: fd = *(int *)rp++;
607: if ((unsigned)fd >= NOFILE || u.u_ofile[fd] == NULL)
608: return (EBADF);
609: }
610: rp = (struct file **)(cm + 1);
611: for (i = 0; i < oldfds; i++) {
612: fp = u.u_ofile[*(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 = file; fp < fileNFILE; fp++)
636: fp->f_flag &= ~(FMARK|FDEFER);
637: do {
638: for (fp = file; fp < fileNFILE; fp++) {
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 = file; fp < fileNFILE; fp++) {
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.