Annotation of sys/compat/svr4/svr4_stream.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: svr4_stream.c,v 1.19 2005/11/21 18:16:38 millert Exp $ */
2: /* $NetBSD: svr4_stream.c,v 1.19 1996/12/22 23:00:03 fvdl Exp $ */
3:
4: /*
5: * Copyright (c) 1994, 1996 Christos Zoulas. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by Christos Zoulas.
18: * 4. The name of the author may not be used to endorse or promote products
19: * derived from this software without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31: */
32:
33: /*
34: * Pretend that we have streams...
35: * Yes, this is gross.
36: *
37: * ToDo: The state machine for getmsg needs re-thinking
38: */
39:
40: #include <sys/param.h>
41: #include <sys/kernel.h>
42: #include <sys/systm.h>
43: #include <sys/buf.h>
44: #include <sys/malloc.h>
45: #include <sys/ioctl.h>
46: #include <sys/tty.h>
47: #include <sys/file.h>
48: #include <sys/filedesc.h>
49: #include <sys/selinfo.h>
50: #include <sys/socket.h>
51: #include <sys/socketvar.h>
52: #include <sys/un.h>
53: #include <net/if.h>
54: #include <netinet/in.h>
55: #include <sys/mount.h>
56: #include <sys/proc.h>
57: #include <sys/vnode.h>
58: #include <sys/device.h>
59: #include <sys/stat.h>
60:
61: #include <sys/syscallargs.h>
62:
63: #include <compat/svr4/svr4_types.h>
64: #include <compat/svr4/svr4_util.h>
65: #include <compat/svr4/svr4_signal.h>
66: #include <compat/svr4/svr4_syscallargs.h>
67: #include <compat/svr4/svr4_stropts.h>
68: #include <compat/svr4/svr4_timod.h>
69: #include <compat/svr4/svr4_sockmod.h>
70: #include <compat/svr4/svr4_ioctl.h>
71: #include <compat/svr4/svr4_socket.h>
72:
73: /* Utils */
74: static int clean_pipe(struct proc *, const char *);
75: static void getparm(struct file *, struct svr4_si_sockparms *);
76:
77: /* Address Conversions */
78: static void sockaddr_to_netaddr_in(struct svr4_strmcmd *,
79: const struct sockaddr_in *);
80: static void sockaddr_to_netaddr_un(struct svr4_strmcmd *,
81: const struct sockaddr_un *);
82: static void netaddr_to_sockaddr_in(struct sockaddr_in *,
83: const struct svr4_strmcmd *);
84: static void netaddr_to_sockaddr_un(struct sockaddr_un *,
85: const struct svr4_strmcmd *);
86:
87: /* stream ioctls */
88: static int i_nread(struct file *, struct proc *, register_t *, int,
89: u_long, caddr_t);
90: static int i_fdinsert(struct file *, struct proc *, register_t *, int,
91: u_long, caddr_t);
92: static int i_str(struct file *, struct proc *, register_t *, int,
93: u_long, caddr_t);
94: static int _i_bind_rsvd(struct file *, struct proc *, register_t *, int,
95: u_long, caddr_t);
96: static int _i_rele_rsvd(struct file *, struct proc *, register_t *, int,
97: u_long, caddr_t);
98:
99: /* i_str sockmod calls */
100: static int sockmod(struct file *, int, struct svr4_strioctl *,
101: struct proc *);
102: static int si_listen(struct file *, int, struct svr4_strioctl *,
103: struct proc *);
104: static int si_ogetudata(struct file *, int, struct svr4_strioctl *,
105: struct proc *);
106: static int si_sockparams(struct file *, int, struct svr4_strioctl *,
107: struct proc *);
108: static int si_shutdown(struct file *, int, struct svr4_strioctl *,
109: struct proc *);
110: static int si_getudata(struct file *, int, struct svr4_strioctl *,
111: struct proc *);
112:
113: /* i_str timod calls */
114: static int timod(struct file *, int, struct svr4_strioctl *,
115: struct proc *);
116: static int ti_getinfo(struct file *, int, struct svr4_strioctl *,
117: struct proc *);
118: static int ti_bind(struct file *, int, struct svr4_strioctl *,
119: struct proc *);
120:
121: #ifdef DEBUG_SVR4
122: static void bufprint(u_char *, size_t);
123: static int show_ioc(const char *, struct svr4_strioctl *);
124: static int show_strbuf(struct svr4_strbuf *);
125: static void show_msg(const char *, int, struct svr4_strbuf *,
126: struct svr4_strbuf *, int);
127:
128: static void
129: bufprint(buf, len)
130: u_char *buf;
131: size_t len;
132: {
133: size_t i;
134:
135: uprintf("\n\t");
136: for (i = 0; i < len; i++) {
137: uprintf("%x ", buf[i]);
138: if (i && (i % 16) == 0)
139: uprintf("\n\t");
140: }
141: }
142:
143: static int
144: show_ioc(str, ioc)
145: const char *str;
146: struct svr4_strioctl *ioc;
147: {
148: u_char *ptr;
149: int error;
150: int len;
151:
152: len = ioc->len;
153: if (len > 1024)
154: len = 1024;
155:
156: if (len <= 0)
157: return 0;
158:
159: ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK);
160: uprintf("%s cmd = %ld, timeout = %d, len = %d, buf = %p { ",
161: str, ioc->cmd, ioc->timeout, ioc->len, ioc->buf);
162:
163: if ((error = copyin(ioc->buf, ptr, len)) != 0) {
164: free((char *) ptr, M_TEMP);
165: return error;
166: }
167:
168: bufprint(ptr, len);
169:
170: uprintf("}\n");
171:
172: free((char *) ptr, M_TEMP);
173: return 0;
174: }
175:
176:
177: static int
178: show_strbuf(str)
179: struct svr4_strbuf *str;
180: {
181: int error;
182: u_char *ptr = NULL;
183: int maxlen = str->maxlen;
184: int len = str->len;
185:
186: if (maxlen > 8192)
187: maxlen = 8192;
188:
189: if (maxlen < 0)
190: maxlen = 0;
191:
192: if (len >= maxlen)
193: len = maxlen;
194:
195: if (len > 0) {
196: ptr = (u_char *)malloc(len, M_TEMP, M_WAITOK);
197:
198: if ((error = copyin(str->buf, ptr, len)) != 0) {
199: free((char *) ptr, M_TEMP);
200: return error;
201: }
202: }
203:
204: uprintf(", { %d, %d, %p=[ ", str->maxlen, str->len, str->buf);
205:
206: if (ptr)
207: bufprint(ptr, len);
208:
209: uprintf("]}");
210:
211: if (ptr)
212: free((char *) ptr, M_TEMP);
213:
214: return 0;
215: }
216:
217:
218: static void
219: show_msg(str, fd, ctl, dat, flags)
220: const char *str;
221: int fd;
222: struct svr4_strbuf *ctl;
223: struct svr4_strbuf *dat;
224: int flags;
225: {
226: struct svr4_strbuf buf;
227: int error;
228:
229: uprintf("%s(%d", str, fd);
230: if (ctl != NULL) {
231: if ((error = copyin(ctl, &buf, sizeof(buf))) != 0)
232: return;
233: show_strbuf(&buf);
234: }
235: else
236: uprintf(", NULL");
237:
238: if (dat != NULL) {
239: if ((error = copyin(dat, &buf, sizeof(buf))) != 0)
240: return;
241: show_strbuf(&buf);
242: }
243: else
244: uprintf(", NULL");
245:
246: uprintf(", %x);\n", flags);
247: }
248: #endif /* DEBUG_SVR4 */
249:
250: /*
251: * We are faced with an interesting situation. On svr4 unix sockets
252: * are really pipes. But we really have sockets, and we might as
253: * well use them. At the point where svr4 calls TI_BIND, it has
254: * already created a named pipe for the socket using mknod(2).
255: * We need to create a socket with the same name when we bind,
256: * so we need to remove the pipe before, otherwise we'll get address
257: * already in use. So we *carefully* remove the pipe, to avoid
258: * using this as a random file removal tool. We use system calls
259: * to avoid code duplication.
260: */
261: static int
262: clean_pipe(p, path)
263: struct proc *p;
264: const char *path;
265: {
266: struct sys_lstat_args la;
267: struct sys_unlink_args ua;
268: register_t retval;
269: struct stat st;
270: int error;
271: caddr_t sg = stackgap_init(p->p_emul);
272: size_t l = strlen(path) + 1;
273:
274: SCARG(&la, path) = stackgap_alloc(&sg, l);
275: SCARG(&la, ub) = stackgap_alloc(&sg, sizeof(struct stat));
276:
277: if ((error = copyout((char *) path, (char *) SCARG(&la, path), l)) != 0)
278: return error;
279:
280: if ((error = sys_lstat(p, &la, &retval)) != 0)
281: return 0;
282:
283: if ((error = copyin(SCARG(&la, ub), &st, sizeof(st))) != 0)
284: return 0;
285:
286: /*
287: * Make sure we are dealing with a mode 0 named pipe.
288: */
289: if ((st.st_mode & S_IFMT) != S_IFIFO)
290: return 0;
291:
292: if ((st.st_mode & ALLPERMS) != 0)
293: return 0;
294:
295: SCARG(&ua, path) = SCARG(&la, path);
296:
297: if ((error = sys_unlink(p, &ua, &retval)) != 0) {
298: DPRINTF(("clean_pipe: unlink failed %d\n", error));
299: return error;
300: }
301:
302: return 0;
303: }
304:
305:
306: static void
307: sockaddr_to_netaddr_in(sc, sain)
308: struct svr4_strmcmd *sc;
309: const struct sockaddr_in *sain;
310: {
311: struct svr4_netaddr_in *na;
312: na = SVR4_ADDROF(sc);
313:
314: na->family = sain->sin_family;
315: na->port = sain->sin_port;
316: na->addr = sain->sin_addr.s_addr;
317: DPRINTF(("sockaddr_in -> netaddr %d %d %lx\n", na->family, na->port,
318: na->addr));
319: }
320:
321:
322: static void
323: sockaddr_to_netaddr_un(sc, saun)
324: struct svr4_strmcmd *sc;
325: const struct sockaddr_un *saun;
326: {
327: struct svr4_netaddr_un *na;
328: char *dst, *edst = ((char *) sc) + sc->offs + sizeof(na->family) + 1 -
329: sizeof(*sc);
330: const char *src;
331:
332: na = SVR4_ADDROF(sc);
333: na->family = saun->sun_family;
334: for (src = saun->sun_path, dst = na->path; (*dst++ = *src++) != '\0'; )
335: if (dst == edst)
336: break;
337: DPRINTF(("sockaddr_un -> netaddr %d %s\n", na->family, na->path));
338: }
339:
340:
341: static void
342: netaddr_to_sockaddr_in(sain, sc)
343: struct sockaddr_in *sain;
344: const struct svr4_strmcmd *sc;
345: {
346: const struct svr4_netaddr_in *na;
347:
348:
349: na = SVR4_ADDROF(sc);
350: bzero(sain, sizeof(*sain));
351: sain->sin_len = sizeof(*sain);
352: sain->sin_family = na->family;
353: sain->sin_port = na->port;
354: sain->sin_addr.s_addr = na->addr;
355: DPRINTF(("netaddr -> sockaddr_in %d %d %x\n", sain->sin_family,
356: sain->sin_port, sain->sin_addr.s_addr));
357: }
358:
359:
360: static void
361: netaddr_to_sockaddr_un(saun, sc)
362: struct sockaddr_un *saun;
363: const struct svr4_strmcmd *sc;
364: {
365: const struct svr4_netaddr_un *na;
366: char *dst, *edst = &saun->sun_path[sizeof(saun->sun_path) - 1];
367: const char *src;
368:
369: na = SVR4_ADDROF(sc);
370: bzero(saun, sizeof(*saun));
371: saun->sun_family = na->family;
372: for (src = na->path, dst = saun->sun_path; (*dst++ = *src++) != '\0'; )
373: if (dst == edst)
374: break;
375: saun->sun_len = dst - saun->sun_path;
376: DPRINTF(("netaddr -> sockaddr_un %d %s\n", saun->sun_family,
377: saun->sun_path));
378: }
379:
380:
381: static void
382: getparm(fp, pa)
383: struct file *fp;
384: struct svr4_si_sockparms *pa;
385: {
386: struct svr4_strm *st = svr4_stream_get(fp);
387: struct socket *so = (struct socket *) fp->f_data;
388:
389: if (st == NULL)
390: return;
391:
392: pa->family = st->s_family;
393:
394: switch (so->so_type) {
395: case SOCK_DGRAM:
396: pa->type = SVR4_SOCK_DGRAM;
397: pa->protocol = IPPROTO_UDP;
398: return;
399:
400: case SOCK_STREAM:
401: pa->type = SVR4_SOCK_STREAM;
402: pa->protocol = IPPROTO_IP;
403: return;
404:
405: case SOCK_RAW:
406: pa->type = SVR4_SOCK_RAW;
407: pa->protocol = IPPROTO_RAW;
408: return;
409:
410: default:
411: pa->type = 0;
412: pa->protocol = 0;
413: return;
414: }
415: }
416:
417:
418: static int
419: si_ogetudata(fp, fd, ioc, p)
420: struct file *fp;
421: int fd;
422: struct svr4_strioctl *ioc;
423: struct proc *p;
424: {
425: int error;
426: struct svr4_si_oudata ud;
427: struct svr4_si_sockparms pa;
428:
429: if (ioc->len != sizeof(ud) && ioc->len != sizeof(ud) - sizeof(int)) {
430: DPRINTF(("SI_OGETUDATA: Wrong size %d != %d\n",
431: sizeof(ud), ioc->len));
432: return EINVAL;
433: }
434:
435: if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
436: return error;
437:
438: getparm(fp, &pa);
439:
440: switch (pa.family) {
441: case AF_INET:
442: ud.tidusize = 16384;
443: ud.addrsize = sizeof(struct sockaddr_in);
444: if (pa.type == SVR4_SOCK_STREAM)
445: ud.etsdusize = 1;
446: else
447: ud.etsdusize = 0;
448: break;
449:
450: case AF_UNIX:
451: ud.tidusize = 65536;
452: ud.addrsize = 128;
453: ud.etsdusize = 128;
454: break;
455:
456: default:
457: DPRINTF(("SI_OGETUDATA: Unsupported address family %d\n",
458: pa.family));
459: return ENOSYS;
460: }
461:
462: /* I have no idea what these should be! */
463: ud.optsize = 128;
464: ud.tsdusize = 128;
465: ud.servtype = pa.type;
466:
467: /* XXX: Fixme */
468: ud.so_state = 0;
469: ud.so_options = 0;
470: return copyout(&ud, ioc->buf, ioc->len);
471: }
472:
473:
474: static int
475: si_sockparams(fp, fd, ioc, p)
476: struct file *fp;
477: int fd;
478: struct svr4_strioctl *ioc;
479: struct proc *p;
480: {
481: struct svr4_si_sockparms pa;
482:
483: getparm(fp, &pa);
484: return copyout(&pa, ioc->buf, sizeof(pa));
485: }
486:
487:
488: static int
489: si_listen(fp, fd, ioc, p)
490: struct file *fp;
491: int fd;
492: struct svr4_strioctl *ioc;
493: struct proc *p;
494: {
495: int error;
496: struct svr4_strm *st = svr4_stream_get(fp);
497: register_t retval;
498: struct svr4_strmcmd lst;
499: struct sys_listen_args la;
500:
501: if (st == NULL)
502: return EINVAL;
503:
504: if (ioc->len > sizeof(lst))
505: return EINVAL;
506:
507: if ((error = copyin(ioc->buf, &lst, ioc->len)) != 0)
508: return error;
509:
510: if (lst.cmd != SVR4_TI_BIND_REQUEST) {
511: DPRINTF(("si_listen: bad request %ld\n", lst.cmd));
512: return EINVAL;
513: }
514:
515: /*
516: * We are making assumptions again...
517: */
518: SCARG(&la, s) = fd;
519: DPRINTF(("SI_LISTEN: fileno %d backlog = %d\n", fd, 5));
520: SCARG(&la, backlog) = 5;
521:
522: if ((error = sys_listen(p, &la, &retval)) != 0) {
523: DPRINTF(("SI_LISTEN: listen failed %d\n", error));
524: return error;
525: }
526:
527: st->s_cmd = SVR4_TI__ACCEPT_WAIT;
528: lst.cmd = SVR4_TI_BIND_REPLY;
529:
530: switch (st->s_family) {
531: case AF_INET:
532: /* XXX: Fill the length here */
533: break;
534:
535: case AF_UNIX:
536: lst.len = 140;
537: lst.pad[28] = 0x00000000; /* magic again */
538: lst.pad[29] = 0x00000800; /* magic again */
539: lst.pad[30] = 0x80001400; /* magic again */
540: break;
541:
542: default:
543: DPRINTF(("SI_LISTEN: Unsupported address family %d\n",
544: st->s_family));
545: return ENOSYS;
546: }
547:
548:
549: if ((error = copyout(&lst, ioc->buf, ioc->len)) != 0)
550: return error;
551:
552: return 0;
553: }
554:
555:
556: static int
557: si_getudata(fp, fd, ioc, p)
558: struct file *fp;
559: int fd;
560: struct svr4_strioctl *ioc;
561: struct proc *p;
562: {
563: int error;
564: struct svr4_si_udata ud;
565:
566: if (sizeof(ud) != ioc->len) {
567: DPRINTF(("SI_GETUDATA: Wrong size %d != %d\n",
568: sizeof(ud), ioc->len));
569: return EINVAL;
570: }
571:
572: if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
573: return error;
574:
575: getparm(fp, &ud.sockparms);
576:
577: switch (ud.sockparms.family) {
578: case AF_INET:
579: ud.tidusize = 16384;
580: ud.tsdusize = 16384;
581: ud.addrsize = sizeof(struct sockaddr_in);
582: if (ud.sockparms.type == SVR4_SOCK_STREAM)
583: ud.etsdusize = 1;
584: else
585: ud.etsdusize = 0;
586: ud.optsize = 0;
587: break;
588:
589: case AF_UNIX:
590: ud.tidusize = 65536;
591: ud.tsdusize = 128;
592: ud.addrsize = 128;
593: ud.etsdusize = 128;
594: ud.optsize = 128;
595: break;
596:
597: default:
598: DPRINTF(("SI_GETUDATA: Unsupported address family %d\n",
599: ud.sockparms.family));
600: return ENOSYS;
601: }
602:
603: ud.servtype = ud.sockparms.type;
604:
605: /* XXX: Fixme */
606: ud.so_state = 0;
607: ud.so_options = 0;
608: return copyout(&ud, ioc->buf, sizeof(ud));
609: }
610:
611:
612: static int
613: si_shutdown(fp, fd, ioc, p)
614: struct file *fp;
615: int fd;
616: struct svr4_strioctl *ioc;
617: struct proc *p;
618: {
619: int error;
620: struct sys_shutdown_args ap;
621: register_t retval;
622:
623: if (ioc->len != sizeof(SCARG(&ap, how))) {
624: DPRINTF(("SI_SHUTDOWN: Wrong size %d != %d\n",
625: sizeof(SCARG(&ap, how)), ioc->len));
626: return EINVAL;
627: }
628:
629: if ((error = copyin(ioc->buf, &SCARG(&ap, how), ioc->len)) != 0)
630: return error;
631:
632: SCARG(&ap, s) = fd;
633:
634: return sys_shutdown(p, &ap, &retval);
635: }
636:
637: static int
638: sockmod(fp, fd, ioc, p)
639: struct file *fp;
640: int fd;
641: struct svr4_strioctl *ioc;
642: struct proc *p;
643: {
644: switch (ioc->cmd) {
645: case SVR4_SI_OGETUDATA:
646: DPRINTF(("SI_OGETUDATA\n"));
647: return si_ogetudata(fp, fd, ioc, p);
648:
649: case SVR4_SI_SHUTDOWN:
650: DPRINTF(("SI_SHUTDOWN\n"));
651: return si_shutdown(fp, fd, ioc, p);
652:
653: case SVR4_SI_LISTEN:
654: DPRINTF(("SI_LISTEN\n"));
655: return si_listen(fp, fd, ioc, p);
656:
657: case SVR4_SI_SETMYNAME:
658: DPRINTF(("SI_SETMYNAME\n"));
659: return 0;
660:
661: case SVR4_SI_SETPEERNAME:
662: DPRINTF(("SI_SETPEERNAME\n"));
663: return 0;
664:
665: case SVR4_SI_GETINTRANSIT:
666: DPRINTF(("SI_GETINTRANSIT\n"));
667: return 0;
668:
669: case SVR4_SI_TCL_LINK:
670: DPRINTF(("SI_TCL_LINK\n"));
671: return 0;
672:
673: case SVR4_SI_TCL_UNLINK:
674: DPRINTF(("SI_TCL_UNLINK\n"));
675: return 0;
676:
677: case SVR4_SI_SOCKPARAMS:
678: DPRINTF(("SI_SOCKPARAMS\n"));
679: return si_sockparams(fp, fd, ioc, p);
680:
681: case SVR4_SI_GETUDATA:
682: DPRINTF(("SI_GETUDATA\n"));
683: return si_getudata(fp, fd, ioc, p);
684:
685: default:
686: DPRINTF(("Unknown sockmod ioctl %lx\n", ioc->cmd));
687: return 0;
688:
689: }
690: }
691:
692:
693: static int
694: ti_getinfo(fp, fd, ioc, p)
695: struct file *fp;
696: int fd;
697: struct svr4_strioctl *ioc;
698: struct proc *p;
699: {
700: int error;
701: struct svr4_infocmd info;
702:
703: bzero(&info, sizeof(info));
704:
705: if (ioc->len > sizeof(info))
706: return EINVAL;
707:
708: if ((error = copyin(ioc->buf, &info, ioc->len)) != 0)
709: return error;
710:
711: if (info.cmd != SVR4_TI_INFO_REQUEST)
712: return EINVAL;
713:
714: info.cmd = SVR4_TI_INFO_REPLY;
715: info.tsdu = 0;
716: info.etsdu = 1;
717: info.cdata = -2;
718: info.ddata = -2;
719: info.addr = 16;
720: info.opt = -1;
721: info.tidu = 16384;
722: info.serv = 2;
723: info.current = 0;
724: info.provider = 2;
725:
726: ioc->len = sizeof(info);
727: if ((error = copyout(&info, ioc->buf, ioc->len)) != 0)
728: return error;
729:
730: return 0;
731: }
732:
733:
734: static int
735: ti_bind(fp, fd, ioc, p)
736: struct file *fp;
737: int fd;
738: struct svr4_strioctl *ioc;
739: struct proc *p;
740: {
741: int error;
742: struct svr4_strm *st = svr4_stream_get(fp);
743: struct sockaddr_in sain;
744: struct sockaddr_un saun;
745: register_t retval;
746: caddr_t sg;
747: void *skp, *sup = NULL;
748: int sasize;
749: struct svr4_strmcmd bnd;
750: struct sys_bind_args ba;
751:
752: if (st == NULL) {
753: DPRINTF(("ti_bind: bad file descriptor\n"));
754: return EINVAL;
755: }
756:
757: if (ioc->len > sizeof(bnd))
758: return EINVAL;
759:
760: if ((error = copyin(ioc->buf, &bnd, ioc->len)) != 0)
761: return error;
762:
763: if (bnd.cmd != SVR4_TI_BIND_REQUEST) {
764: DPRINTF(("ti_bind: bad request %ld\n", bnd.cmd));
765: return EINVAL;
766: }
767:
768: switch (st->s_family) {
769: case AF_INET:
770: skp = &sain;
771: sasize = sizeof(sain);
772:
773: if (bnd.offs == 0)
774: goto reply;
775:
776: netaddr_to_sockaddr_in(&sain, &bnd);
777:
778: DPRINTF(("TI_BIND: fam %d, port %d, addr %x\n",
779: sain.sin_family, sain.sin_port,
780: sain.sin_addr.s_addr));
781: break;
782:
783: case AF_UNIX:
784: skp = &saun;
785: sasize = sizeof(saun);
786: if (bnd.offs == 0)
787: goto reply;
788:
789: netaddr_to_sockaddr_un(&saun, &bnd);
790:
791: if (saun.sun_path[0] == '\0')
792: goto reply;
793:
794: DPRINTF(("TI_BIND: fam %d, path %s\n",
795: saun.sun_family, saun.sun_path));
796:
797: if ((error = clean_pipe(p, saun.sun_path)) != 0)
798: return error;
799:
800: bnd.pad[28] = 0x00001000; /* magic again */
801: break;
802:
803: default:
804: DPRINTF(("TI_BIND: Unsupported address family %d\n",
805: st->s_family));
806: return ENOSYS;
807: }
808:
809: sg = stackgap_init(p->p_emul);
810: sup = stackgap_alloc(&sg, sasize);
811:
812: if ((error = copyout(skp, sup, sasize)) != 0)
813: return error;
814:
815: SCARG(&ba, s) = fd;
816: DPRINTF(("TI_BIND: fileno %d\n", fd));
817: SCARG(&ba, name) = (void *)sup;
818: SCARG(&ba, namelen) = sasize;
819:
820: if ((error = sys_bind(p, &ba, &retval)) != 0) {
821: DPRINTF(("TI_BIND: bind failed %d\n", error));
822: return error;
823: }
824:
825: reply:
826: if (sup == NULL) {
827: bzero(&bnd, sizeof(bnd));
828: bnd.len = sasize + 4;
829: bnd.offs = 0x10; /* XXX */
830: }
831:
832: bnd.cmd = SVR4_TI_BIND_REPLY;
833:
834: if ((error = copyout(&bnd, ioc->buf, ioc->len)) != 0)
835: return error;
836:
837: return 0;
838: }
839:
840:
841: static int
842: timod(fp, fd, ioc, p)
843: struct file *fp;
844: int fd;
845: struct svr4_strioctl *ioc;
846: struct proc *p;
847: {
848: switch (ioc->cmd) {
849: case SVR4_TI_GETINFO:
850: DPRINTF(("TI_GETINFO\n"));
851: return ti_getinfo(fp, fd, ioc, p);
852:
853: case SVR4_TI_OPTMGMT:
854: DPRINTF(("TI_OPTMGMT\n"));
855: return 0;
856:
857: case SVR4_TI_BIND:
858: DPRINTF(("TI_BIND\n"));
859: return ti_bind(fp, fd, ioc, p);
860:
861: case SVR4_TI_UNBIND:
862: DPRINTF(("TI_UNBIND\n"));
863: return 0;
864:
865: default:
866: DPRINTF(("Unknown timod ioctl %lx\n", ioc->cmd));
867: return 0;
868: }
869: }
870:
871:
872: int
873: svr4_stream_ti_ioctl(fp, p, retval, fd, cmd, dat)
874: struct file *fp;
875: struct proc *p;
876: register_t *retval;
877: int fd;
878: u_long cmd;
879: caddr_t dat;
880: {
881: struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat;
882: struct svr4_strm *st = svr4_stream_get(fp);
883: int error;
884: void *skp, *sup;
885: struct sockaddr_in sain;
886: struct sockaddr_un saun;
887: struct svr4_strmcmd sc;
888: socklen_t sasize, samax;
889: caddr_t sg;
890: int *lenp;
891:
892: if (st == NULL)
893: return EINVAL;
894:
895: sc.offs = 0x10;
896:
897: switch (st->s_family) {
898: case AF_INET:
899: skp = &sain;
900: samax = sizeof(sain);
901: break;
902:
903: case AF_UNIX:
904: skp = &saun;
905: samax = sizeof(saun);
906: break;
907:
908: default:
909: DPRINTF(("ti_ioctl: Unsupported address family %d\n",
910: st->s_family));
911: return ENOSYS;
912: }
913:
914: sg = stackgap_init(p->p_emul);
915: sup = stackgap_alloc(&sg, samax);
916: lenp = stackgap_alloc(&sg, sizeof(*lenp));
917:
918: if ((error = copyout(&samax, lenp, sizeof(*lenp))) != 0) {
919: DPRINTF(("ti_ioctl: error copying out lenp\n"));
920: return error;
921: }
922:
923: switch (cmd) {
924: case SVR4_TI_GETMYNAME:
925: DPRINTF(("TI_GETMYNAME\n"));
926: {
927: struct sys_getsockname_args ap;
928: SCARG(&ap, fdes) = fd;
929: SCARG(&ap, asa) = sup;
930: SCARG(&ap, alen) = lenp;
931: if ((error = sys_getsockname(p, &ap, retval)) != 0) {
932: DPRINTF(("ti_ioctl: getsockname error\n"));
933: return error;
934: }
935: }
936: break;
937:
938: case SVR4_TI_GETPEERNAME:
939: DPRINTF(("TI_GETPEERNAME\n"));
940: {
941: struct sys_getpeername_args ap;
942: SCARG(&ap, fdes) = fd;
943: SCARG(&ap, asa) = sup;
944: SCARG(&ap, alen) = lenp;
945: if ((error = sys_getpeername(p, &ap, retval)) != 0) {
946: DPRINTF(("ti_ioctl: getpeername error\n"));
947: return error;
948: }
949: }
950: break;
951:
952: case SVR4_TI_SETMYNAME:
953: DPRINTF(("TI_SETMYNAME\n"));
954: return 0;
955:
956: case SVR4_TI_SETPEERNAME:
957: DPRINTF(("TI_SETPEERNAME\n"));
958: return 0;
959: default:
960: DPRINTF(("ti_ioctl: Unknown ioctl %lx\n", cmd));
961: return ENOSYS;
962: }
963:
964: if ((error = copyin(sup, skp, samax)) != 0) {
965: DPRINTF(("ti_ioctl: error copying in socket data\n"));
966: return error;
967: }
968:
969: if ((error = copyin(lenp, &sasize, sizeof(*lenp))) != 0) {
970: DPRINTF(("ti_ioctl: error copying in socket size\n"));
971: return error;
972: }
973:
974: if (sasize < 0 || sasize > samax) {
975: DPRINTF(("ti_ioctl: invalid socklen on stack\n"));
976: error = EINVAL;
977: return error;
978: }
979:
980: if ((error = copyin(sub, &skb, sizeof(skb))) != 0) {
981: DPRINTF(("ti_ioctl: error copying in strbuf\n"));
982: return error;
983: }
984:
985: switch (st->s_family) {
986: case AF_INET:
987: sockaddr_to_netaddr_in(&sc, &sain);
988: skb.len = sasize;
989: break;
990:
991: case AF_UNIX:
992: sockaddr_to_netaddr_un(&sc, &saun);
993: skb.len = sasize + 4;
994: break;
995:
996: default:
997: return ENOSYS;
998: }
999:
1000: if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) {
1001: DPRINTF(("ti_ioctl: error copying out socket data\n"));
1002: return error;
1003: }
1004:
1005: if ((error = copyout(&skb, sub, sizeof(skb))) != 0) {
1006: DPRINTF(("ti_ioctl: error copying out strbuf\n"));
1007: return error;
1008: }
1009:
1010: return error;
1011: }
1012:
1013: static int
1014: i_nread(fp, p, retval, fd, cmd, dat)
1015: struct file *fp;
1016: struct proc *p;
1017: register_t *retval;
1018: int fd;
1019: u_long cmd;
1020: caddr_t dat;
1021: {
1022: int error;
1023: int nread = 0;
1024:
1025: /*
1026: * We are supposed to return the message length in nread, and the
1027: * number of messages in retval. We don't have the notion of number
1028: * of stream messages, so we just find out if we have any bytes waiting
1029: * for us, and if we do, then we assume that we have at least one
1030: * message waiting for us.
1031: */
1032: if ((error = (*fp->f_ops->fo_ioctl)(fp, FIONREAD,
1033: (caddr_t) &nread, p)) != 0)
1034: return error;
1035:
1036: if (nread != 0)
1037: *retval = 1;
1038: else
1039: *retval = 0;
1040:
1041: return copyout(&nread, dat, sizeof(nread));
1042: }
1043:
1044: static int
1045: i_fdinsert(fp, p, retval, fd, cmd, dat)
1046: struct file *fp;
1047: struct proc *p;
1048: register_t *retval;
1049: int fd;
1050: u_long cmd;
1051: caddr_t dat;
1052: {
1053: /*
1054: * Major hack again here. We assume that we are using this to
1055: * implement accept(2). If that is the case, we have already
1056: * called accept, and we have stored the file descriptor in
1057: * afd. We find the file descriptor that the code wants to use
1058: * in fd insert, and then we dup2() our accepted file descriptor
1059: * to it.
1060: */
1061: int error;
1062: struct svr4_strm *st = svr4_stream_get(fp);
1063: struct svr4_strfdinsert fdi;
1064: struct sys_dup2_args d2p;
1065: struct sys_close_args clp;
1066:
1067: if (st == NULL) {
1068: DPRINTF(("fdinsert: bad file type\n"));
1069: return EINVAL;
1070: }
1071:
1072: if (st->s_afd == -1) {
1073: DPRINTF(("fdinsert: accept fd not found\n"));
1074: return ENOENT;
1075: }
1076:
1077: if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) {
1078: DPRINTF(("fdinsert: copyin failed %d\n", error));
1079: return error;
1080: }
1081:
1082: SCARG(&d2p, from) = st->s_afd;
1083: SCARG(&d2p, to) = fdi.fd;
1084:
1085: if ((error = sys_dup2(p, &d2p, retval)) != 0) {
1086: DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n",
1087: st->s_afd, fdi.fd, error));
1088: return error;
1089: }
1090:
1091: SCARG(&clp, fd) = st->s_afd;
1092:
1093: if ((error = sys_close(p, &clp, retval)) != 0) {
1094: DPRINTF(("fdinsert: close(%d) failed %d\n",
1095: st->s_afd, error));
1096: return error;
1097: }
1098:
1099: st->s_afd = -1;
1100:
1101: *retval = 0;
1102: return 0;
1103: }
1104:
1105:
1106: static int
1107: _i_bind_rsvd(fp, p, retval, fd, cmd, dat)
1108: struct file *fp;
1109: struct proc *p;
1110: register_t *retval;
1111: int fd;
1112: u_long cmd;
1113: caddr_t dat;
1114: {
1115: struct sys_mknod_args ap;
1116:
1117: /*
1118: * This is a supposed to be a kernel and library only ioctl.
1119: * It gets called before ti_bind, when we have a unix
1120: * socket, to physically create the socket transport and
1121: * ``reserve'' it. I don't know how this get reserved inside
1122: * the kernel, but we are going to create it nevertheless.
1123: */
1124: SCARG(&ap, path) = dat;
1125: SCARG(&ap, mode) = S_IFIFO;
1126:
1127: return sys_mkfifo(p, &ap, retval);
1128: }
1129:
1130: static int
1131: _i_rele_rsvd(fp, p, retval, fd, cmd, dat)
1132: struct file *fp;
1133: struct proc *p;
1134: register_t *retval;
1135: int fd;
1136: u_long cmd;
1137: caddr_t dat;
1138: {
1139: struct sys_unlink_args ap;
1140:
1141: /*
1142: * This is a supposed to be a kernel and library only ioctl.
1143: * I guess it is supposed to release the socket.
1144: */
1145: SCARG(&ap, path) = dat;
1146:
1147: return sys_unlink(p, &ap, retval);
1148: }
1149:
1150: static int
1151: i_str(fp, p, retval, fd, cmd, dat)
1152: struct file *fp;
1153: struct proc *p;
1154: register_t *retval;
1155: int fd;
1156: u_long cmd;
1157: caddr_t dat;
1158: {
1159: int error;
1160: struct svr4_strioctl ioc;
1161:
1162: if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0)
1163: return error;
1164:
1165: #ifdef DEBUG_SVR4
1166: if ((error = show_ioc(">", &ioc)) != 0)
1167: return error;
1168: #endif /* DEBUG_SVR4 */
1169:
1170: switch (ioc.cmd & 0xff00) {
1171: case SVR4_SIMOD:
1172: if ((error = sockmod(fp, fd, &ioc, p)) != 0)
1173: return error;
1174: break;
1175:
1176: case SVR4_TIMOD:
1177: if ((error = timod(fp, fd, &ioc, p)) != 0)
1178: return error;
1179: break;
1180:
1181: default:
1182: DPRINTF(("Unimplemented module %c %ld\n",
1183: (char) (cmd >> 8), cmd & 0xff));
1184: return 0;
1185: }
1186:
1187: #ifdef DEBUG_SVR4
1188: if ((error = show_ioc("<", &ioc)) != 0)
1189: return error;
1190: #endif /* DEBUG_SVR4 */
1191: return copyout(&ioc, dat, sizeof(ioc));
1192: }
1193:
1194:
1195: int
1196: svr4_stream_ioctl(fp, p, retval, fd, cmd, dat)
1197: struct file *fp;
1198: struct proc *p;
1199: register_t *retval;
1200: int fd;
1201: u_long cmd;
1202: caddr_t dat;
1203: {
1204: *retval = 0;
1205:
1206: /*
1207: * All the following stuff assumes "sockmod" is pushed...
1208: */
1209: switch (cmd) {
1210: case SVR4_I_NREAD:
1211: DPRINTF(("I_NREAD\n"));
1212: return i_nread(fp, p, retval, fd, cmd, dat);
1213:
1214: case SVR4_I_PUSH:
1215: DPRINTF(("I_PUSH\n"));
1216: return 0;
1217:
1218: case SVR4_I_POP:
1219: DPRINTF(("I_POP\n"));
1220: return 0;
1221:
1222: case SVR4_I_LOOK:
1223: DPRINTF(("I_LOOK\n"));
1224: return 0;
1225:
1226: case SVR4_I_FLUSH:
1227: DPRINTF(("I_FLUSH\n"));
1228: return 0;
1229:
1230: case SVR4_I_SRDOPT:
1231: DPRINTF(("I_SRDOPT\n"));
1232: return 0;
1233:
1234: case SVR4_I_GRDOPT:
1235: DPRINTF(("I_GRDOPT\n"));
1236: return 0;
1237:
1238: case SVR4_I_STR:
1239: DPRINTF(("I_STR\n"));
1240: return i_str(fp, p, retval, fd, cmd, dat);
1241:
1242: case SVR4_I_SETSIG:
1243: DPRINTF(("I_SETSIG\n"));
1244: /*
1245: * This is the best we can do for now; we cannot generate
1246: * signals only for specific events so the signal mask gets
1247: * ignored.
1248: *
1249: * We alse have to fix the O_ASYNC fcntl bit, so the
1250: * process will get SIGPOLLs. */
1251: {
1252: struct sys_fcntl_args fa;
1253: int error;
1254: register_t oflags, flags;
1255:
1256: /* get old status flags */
1257: SCARG(&fa, fd) = fd;
1258: SCARG(&fa, cmd) = F_GETFL;
1259: if ((error = sys_fcntl(p, &fa, &oflags)) != 0)
1260: return error;
1261:
1262: /* update the flags */
1263: if ((long) dat != 0)
1264: flags = oflags | O_ASYNC;
1265: else
1266: flags = oflags & ~O_ASYNC;
1267:
1268: /* set the new flags, if changed */
1269: if (flags != oflags) {
1270: SCARG(&fa, cmd) = F_SETFL;
1271: SCARG(&fa, arg) = (void *) flags;
1272: if ((error = sys_fcntl(p, &fa, &flags)) != 0)
1273: return error;
1274: }
1275:
1276: /* set up SIGIO receiver if needed */
1277: if ((long) dat != 0) {
1278: SCARG(&fa, cmd) = F_SETOWN;
1279: SCARG(&fa, arg) = (void *) p->p_pid;
1280: return sys_fcntl(p, &fa, retval);
1281: }
1282: }
1283:
1284: case SVR4_I_GETSIG:
1285: DPRINTF(("I_GETSIG\n"));
1286: return EINVAL;
1287:
1288: case SVR4_I_FIND:
1289: DPRINTF(("I_FIND\n"));
1290: /*
1291: * Here we are not pushing modules really, we just
1292: * pretend all are present
1293: */
1294: *retval = 1;
1295: return 0;
1296:
1297: case SVR4_I_LINK:
1298: DPRINTF(("I_LINK\n"));
1299: return 0;
1300:
1301: case SVR4_I_UNLINK:
1302: DPRINTF(("I_UNLINK\n"));
1303: return 0;
1304:
1305: case SVR4_I_ERECVFD:
1306: DPRINTF(("I_ERECVFD\n"));
1307: return 0;
1308:
1309: case SVR4_I_PEEK:
1310: DPRINTF(("I_PEEK\n"));
1311: return 0;
1312:
1313: case SVR4_I_FDINSERT:
1314: DPRINTF(("I_FDINSERT\n"));
1315: return i_fdinsert(fp, p, retval, fd, cmd, dat);
1316:
1317: case SVR4_I_SENDFD:
1318: DPRINTF(("I_SENDFD\n"));
1319: return 0;
1320:
1321: case SVR4_I_RECVFD:
1322: DPRINTF(("I_RECVFD\n"));
1323: return 0;
1324:
1325: case SVR4_I_SWROPT:
1326: DPRINTF(("I_SWROPT\n"));
1327: return 0;
1328:
1329: case SVR4_I_GWROPT:
1330: DPRINTF(("I_GWROPT\n"));
1331: return 0;
1332:
1333: case SVR4_I_LIST:
1334: DPRINTF(("I_LIST\n"));
1335: return 0;
1336:
1337: case SVR4_I_PLINK:
1338: DPRINTF(("I_PLINK\n"));
1339: return 0;
1340:
1341: case SVR4_I_PUNLINK:
1342: DPRINTF(("I_PUNLINK\n"));
1343: return 0;
1344:
1345: case SVR4_I_SETEV:
1346: DPRINTF(("I_SETEV\n"));
1347: return 0;
1348:
1349: case SVR4_I_GETEV:
1350: DPRINTF(("I_GETEV\n"));
1351: return 0;
1352:
1353: case SVR4_I_STREV:
1354: DPRINTF(("I_STREV\n"));
1355: return 0;
1356:
1357: case SVR4_I_UNSTREV:
1358: DPRINTF(("I_UNSTREV\n"));
1359: return 0;
1360:
1361: case SVR4_I_FLUSHBAND:
1362: DPRINTF(("I_FLUSHBAND\n"));
1363: return 0;
1364:
1365: case SVR4_I_CKBAND:
1366: DPRINTF(("I_CKBAND\n"));
1367: return 0;
1368:
1369: case SVR4_I_GETBAND:
1370: DPRINTF(("I_GETBANK\n"));
1371: return 0;
1372:
1373: case SVR4_I_ATMARK:
1374: DPRINTF(("I_ATMARK\n"));
1375: return 0;
1376:
1377: case SVR4_I_SETCLTIME:
1378: DPRINTF(("I_SETCLTIME\n"));
1379: return 0;
1380:
1381: case SVR4_I_GETCLTIME:
1382: DPRINTF(("I_GETCLTIME\n"));
1383: return 0;
1384:
1385: case SVR4_I_CANPUT:
1386: DPRINTF(("I_CANPUT\n"));
1387: return 0;
1388:
1389: case SVR4__I_BIND_RSVD:
1390: DPRINTF(("_I_BIND_RSVD\n"));
1391: return _i_bind_rsvd(fp, p, retval, fd, cmd, dat);
1392:
1393: case SVR4__I_RELE_RSVD:
1394: DPRINTF(("_I_RELE_RSVD\n"));
1395: return _i_rele_rsvd(fp, p, retval, fd, cmd, dat);
1396:
1397: default:
1398: DPRINTF(("unimpl cmd = %lx\n", cmd));
1399: break;
1400: }
1401:
1402: return 0;
1403: }
1404:
1405:
1406:
1407:
1408: int
1409: svr4_sys_putmsg(p, v, retval)
1410: register struct proc *p;
1411: void *v;
1412: register_t *retval;
1413: {
1414: struct svr4_sys_putmsg_args *uap = v;
1415: struct filedesc *fdp = p->p_fd;
1416: struct file *fp;
1417: struct svr4_strbuf dat, ctl;
1418: struct svr4_strmcmd sc;
1419: struct sockaddr_in sain;
1420: struct sockaddr_un saun;
1421: void *skp, *sup;
1422: int sasize;
1423: struct svr4_strm *st;
1424: int error;
1425: caddr_t sg;
1426:
1427: #ifdef DEBUG_SVR4
1428: show_msg(">putmsg", SCARG(uap, fd), SCARG(uap, ctl),
1429: SCARG(uap, dat), SCARG(uap, flags));
1430: #endif /* DEBUG_SVR4 */
1431:
1432: if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
1433: return EBADF;
1434: FREF(fp);
1435:
1436: if (SCARG(uap, ctl) != NULL) {
1437: if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0)
1438: goto out;
1439: }
1440: else
1441: ctl.len = -1;
1442:
1443: if (SCARG(uap, dat) != NULL) {
1444: if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0)
1445: goto out;
1446: }
1447: else
1448: dat.len = -1;
1449:
1450: /*
1451: * Only for sockets for now.
1452: */
1453: if ((st = svr4_stream_get(fp)) == NULL) {
1454: DPRINTF(("putmsg: bad file type\n"));
1455: error = EINVAL;
1456: goto out;
1457: }
1458:
1459: if (ctl.len > sizeof(sc)) {
1460: DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len,
1461: sizeof(struct svr4_strmcmd)));
1462: error = EINVAL;
1463: goto out;
1464: }
1465:
1466: if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
1467: goto out;
1468:
1469: switch (st->s_family) {
1470: case AF_INET:
1471: if (sc.len != sizeof(sain)) {
1472: DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len));
1473: error = ENOSYS;
1474: goto out;
1475: }
1476: netaddr_to_sockaddr_in(&sain, &sc);
1477: skp = &sain;
1478: sasize = sizeof(sain);
1479: error = sain.sin_family != st->s_family;
1480: break;
1481:
1482: case AF_UNIX:
1483: if (ctl.len == 8) {
1484: /* We are doing an accept; succeed */
1485: DPRINTF(("putmsg: Do nothing\n"));
1486: *retval = 0;
1487: error = 0;
1488: goto out;
1489: } else {
1490: /* Maybe we've been given a device/inode pair */
1491: dev_t *dev = SVR4_ADDROF(&sc);
1492: ino_t *ino = (ino_t *) &dev[1];
1493: skp = svr4_find_socket(p, fp, *dev, *ino);
1494: if (skp == NULL) {
1495: skp = &saun;
1496: /* I guess we have it by name */
1497: netaddr_to_sockaddr_un(skp, &sc);
1498: }
1499: sasize = sizeof(saun);
1500: }
1501: break;
1502:
1503: default:
1504: DPRINTF(("putmsg: Unsupported address family %d\n",
1505: st->s_family));
1506: error = ENOSYS;
1507: goto out;
1508: }
1509:
1510: sg = stackgap_init(p->p_emul);
1511: sup = stackgap_alloc(&sg, sasize);
1512:
1513: if ((error = copyout(skp, sup, sasize)) != 0)
1514: goto out;
1515:
1516: switch (st->s_cmd = sc.cmd) {
1517: case SVR4_TI_CONNECT_REQUEST: /* connect */
1518: {
1519: struct sys_connect_args co;
1520:
1521: SCARG(&co, s) = SCARG(uap, fd);
1522: SCARG(&co, name) = (void *)sup;
1523: SCARG(&co, namelen) = (int)sasize;
1524: error = sys_connect(p, &co, retval);
1525: goto out;
1526: }
1527:
1528: case SVR4_TI_SENDTO_REQUEST: /* sendto */
1529: {
1530: struct msghdr msg;
1531: struct iovec aiov;
1532:
1533: msg.msg_name = (caddr_t) sup;
1534: msg.msg_namelen = sasize;
1535: msg.msg_iov = &aiov;
1536: msg.msg_iovlen = 1;
1537: msg.msg_control = 0;
1538: msg.msg_flags = 0;
1539: aiov.iov_base = dat.buf;
1540: aiov.iov_len = dat.len;
1541: error = sendit(p, SCARG(uap, fd), &msg,
1542: SCARG(uap, flags), retval);
1543:
1544: *retval = 0;
1545: goto out;
1546: }
1547:
1548: default:
1549: DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd));
1550: error = ENOSYS;
1551: goto out;
1552: }
1553:
1554: out:
1555: FRELE(fp);
1556: return (error);
1557: }
1558:
1559:
1560: int
1561: svr4_sys_getmsg(p, v, retval)
1562: register struct proc *p;
1563: void *v;
1564: register_t *retval;
1565: {
1566: struct svr4_sys_getmsg_args *uap = v;
1567: struct filedesc *fdp = p->p_fd;
1568: struct file *fp;
1569: struct sys_getpeername_args ga;
1570: struct sys_accept_args aa;
1571: struct svr4_strbuf dat, ctl;
1572: struct svr4_strmcmd sc;
1573: int error;
1574: struct msghdr msg;
1575: struct iovec aiov;
1576: struct sockaddr_in sain;
1577: struct sockaddr_un saun;
1578: void *skp, *sup;
1579: int sasize;
1580: struct svr4_strm *st;
1581: int *flen;
1582: int fl;
1583: caddr_t sg;
1584:
1585: bzero(&sc, sizeof(sc));
1586:
1587: #ifdef DEBUG_SVR4
1588: show_msg(">getmsg", SCARG(uap, fd), SCARG(uap, ctl),
1589: SCARG(uap, dat), 0);
1590: #endif /* DEBUG_SVR4 */
1591:
1592: if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
1593: return EBADF;
1594: FREF(fp);
1595:
1596: if (SCARG(uap, ctl) != NULL) {
1597: if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0)
1598: goto out;
1599: }
1600: else {
1601: ctl.len = -1;
1602: ctl.maxlen = 0;
1603: }
1604:
1605: if (SCARG(uap, dat) != NULL) {
1606: if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0)
1607: goto out;
1608: }
1609: else {
1610: dat.len = -1;
1611: dat.maxlen = 0;
1612: }
1613:
1614: /*
1615: * Only for sockets for now.
1616: */
1617: if ((st = svr4_stream_get(fp)) == NULL) {
1618: DPRINTF(("getmsg: bad file type\n"));
1619: error = EINVAL;
1620: goto out;
1621: }
1622:
1623: if (ctl.maxlen == -1 || dat.maxlen == -1) {
1624: DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n"));
1625: error = ENOSYS;
1626: goto out;
1627: }
1628:
1629: switch (st->s_family) {
1630: case AF_INET:
1631: skp = &sain;
1632: sasize = sizeof(sain);
1633: break;
1634:
1635: case AF_UNIX:
1636: skp = &saun;
1637: sasize = sizeof(saun);
1638: break;
1639:
1640: default:
1641: DPRINTF(("getmsg: Unsupported address family %d\n",
1642: st->s_family));
1643: error = ENOSYS;
1644: goto out;
1645: }
1646:
1647: sg = stackgap_init(p->p_emul);
1648: sup = stackgap_alloc(&sg, sasize);
1649: flen = (int *) stackgap_alloc(&sg, sizeof(*flen));
1650:
1651: fl = sasize;
1652: if ((error = copyout(&fl, flen, sizeof(fl))) != 0)
1653: goto out;
1654:
1655: switch (st->s_cmd) {
1656: case SVR4_TI_CONNECT_REQUEST:
1657: DPRINTF(("getmsg: TI_CONNECT_REQUEST\n"));
1658: /*
1659: * We do the connect in one step, so the putmsg should
1660: * have gotten the error.
1661: */
1662: sc.cmd = SVR4_TI_OK_REPLY;
1663: sc.len = 0;
1664:
1665: ctl.len = 8;
1666: dat.len = -1;
1667: fl = 1;
1668: st->s_cmd = sc.cmd;
1669: break;
1670:
1671: case SVR4_TI_OK_REPLY:
1672: DPRINTF(("getmsg: TI_OK_REPLY\n"));
1673:
1674: /*
1675: * We are immediately after a connect reply, so we send
1676: * a connect verification.
1677: */
1678: SCARG(&ga, fdes) = SCARG(uap, fd);
1679: SCARG(&ga, asa) = (void *)sup;
1680: SCARG(&ga, alen) = flen;
1681:
1682: if ((error = sys_getpeername(p, &ga, retval)) != 0) {
1683: DPRINTF(("getmsg: getpeername failed %d\n", error));
1684: goto out;
1685: }
1686:
1687: if ((error = copyin(sup, skp, sasize)) != 0)
1688: goto out;
1689:
1690: sc.cmd = SVR4_TI_CONNECT_REPLY;
1691: sc.pad[0] = 0x4;
1692: sc.offs = 0x18;
1693: sc.pad[1] = 0x14;
1694: sc.pad[2] = 0x04000402;
1695:
1696: switch (st->s_family) {
1697: case AF_INET:
1698: sc.len = sasize;
1699: sockaddr_to_netaddr_in(&sc, &sain);
1700: break;
1701:
1702: case AF_UNIX:
1703: sc.len = sasize + 4;
1704: sockaddr_to_netaddr_un(&sc, &saun);
1705: break;
1706:
1707: default:
1708: error = ENOSYS;
1709: goto out;
1710: }
1711:
1712: ctl.len = 40;
1713: dat.len = -1;
1714: fl = 0;
1715: st->s_cmd = sc.cmd;
1716: break;
1717:
1718: case SVR4_TI__ACCEPT_OK:
1719: DPRINTF(("getmsg: TI__ACCEPT_OK\n"));
1720: /*
1721: * We do the connect in one step, so the putmsg should
1722: * have gotten the error.
1723: */
1724: sc.cmd = SVR4_TI_OK_REPLY;
1725: sc.len = 1;
1726:
1727: ctl.len = 8;
1728: dat.len = -1;
1729: fl = 1;
1730: st->s_cmd = SVR4_TI__ACCEPT_WAIT;
1731: break;
1732:
1733: case SVR4_TI__ACCEPT_WAIT:
1734: DPRINTF(("getmsg: TI__ACCEPT_WAIT\n"));
1735: /*
1736: * We are after a listen, so we try to accept...
1737: */
1738: SCARG(&aa, s) = SCARG(uap, fd);
1739: SCARG(&aa, name) = (void *)sup;
1740: SCARG(&aa, anamelen) = flen;
1741:
1742: if ((error = sys_accept(p, &aa, retval)) != 0) {
1743: DPRINTF(("getmsg: accept failed %d\n", error));
1744: goto out;
1745: }
1746:
1747: st->s_afd = *retval;
1748:
1749: DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd));
1750:
1751: if ((error = copyin(sup, skp, sasize)) != 0)
1752: goto out;
1753:
1754: sc.cmd = SVR4_TI_ACCEPT_REPLY;
1755: sc.len = sasize;
1756: sc.offs = 0x18;
1757: sc.pad[0] = 0x0;
1758: sc.pad[1] = 0x28;
1759: sc.pad[2] = 0x3;
1760:
1761: switch (st->s_family) {
1762: case AF_INET:
1763: sc.pad[1] = 0x28;
1764: sockaddr_to_netaddr_in(&sc, &sain);
1765: ctl.len = 40;
1766: sc.len = sasize;
1767: break;
1768:
1769: case AF_UNIX:
1770: sc.pad[1] = 0x00010000;
1771: sc.pad[2] = 0xf6bcdaa0; /* I don't know what that is */
1772: sc.pad[3] = 0x00010000;
1773: ctl.len = 134;
1774: sc.len = sasize + 4;
1775: break;
1776:
1777: default:
1778: error = ENOSYS;
1779: goto out;
1780: }
1781:
1782: ctl.len = 40;
1783: dat.len = -1;
1784: fl = 0;
1785: st->s_cmd = SVR4_TI__ACCEPT_OK;
1786: break;
1787:
1788: case SVR4_TI_SENDTO_REQUEST:
1789: DPRINTF(("getmsg: TI_SENDTO_REQUEST\n"));
1790: if (ctl.maxlen > 36 && ctl.len < 36)
1791: ctl.len = 36;
1792:
1793: if (ctl.len > sizeof(sc))
1794: ctl.len = sizeof(sc);
1795:
1796: if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
1797: goto out;
1798:
1799: switch (st->s_family) {
1800: case AF_INET:
1801: sockaddr_to_netaddr_in(&sc, &sain);
1802: break;
1803:
1804: case AF_UNIX:
1805: sockaddr_to_netaddr_un(&sc, &saun);
1806: break;
1807:
1808: default:
1809: error = ENOSYS;
1810: goto out;
1811: }
1812:
1813: msg.msg_name = (caddr_t) sup;
1814: msg.msg_namelen = sasize;
1815: msg.msg_iov = &aiov;
1816: msg.msg_iovlen = 1;
1817: msg.msg_control = 0;
1818: aiov.iov_base = dat.buf;
1819: aiov.iov_len = dat.maxlen;
1820: msg.msg_flags = 0;
1821:
1822: error = recvit(p, SCARG(uap, fd), &msg, (caddr_t) flen, retval);
1823:
1824: if (error) {
1825: DPRINTF(("getmsg: recvit failed %d\n", error));
1826: goto out;
1827: }
1828:
1829: if ((error = copyin(msg.msg_name, skp, sasize)) != 0)
1830: goto out;
1831:
1832: sc.cmd = SVR4_TI_RECVFROM_REPLY;
1833:
1834: switch (st->s_family) {
1835: case AF_INET:
1836: sc.len = sasize;
1837: sockaddr_to_netaddr_in(&sc, &sain);
1838: break;
1839:
1840: case AF_UNIX:
1841: sc.len = sasize + 4;
1842: sockaddr_to_netaddr_un(&sc, &saun);
1843: break;
1844:
1845: default:
1846: error = ENOSYS;
1847: goto out;
1848: }
1849:
1850: dat.len = *retval;
1851: fl = 0;
1852: st->s_cmd = sc.cmd;
1853: break;
1854:
1855: default:
1856: st->s_cmd = sc.cmd;
1857: DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd));
1858: error = EINVAL;
1859: goto out;
1860: }
1861:
1862: if (SCARG(uap, ctl)) {
1863: if (ctl.len != -1)
1864: if ((error = copyout(&sc, ctl.buf, ctl.len)) != 0)
1865: goto out;
1866:
1867: if ((error = copyout(&ctl, SCARG(uap, ctl), sizeof(ctl))) != 0)
1868: goto out;
1869: }
1870:
1871: if (SCARG(uap, dat)) {
1872: if ((error = copyout(&dat, SCARG(uap, dat), sizeof(dat))) != 0)
1873: goto out;
1874: }
1875:
1876: if (SCARG(uap, flags)) { /* XXX: Need translation */
1877: if ((error = copyout(&fl, SCARG(uap, flags), sizeof(fl))) != 0)
1878: goto out;
1879: }
1880:
1881: *retval = 0;
1882:
1883: #ifdef DEBUG_SVR4
1884: show_msg("<getmsg", SCARG(uap, fd), SCARG(uap, ctl),
1885: SCARG(uap, dat), fl);
1886: #endif /* DEBUG_SVR4 */
1887: out:
1888: FRELE(fp);
1889: return error;
1890: }
CVSweb