No empty .Rs/.Re
[netbsd-mini2440.git] / sys / compat / svr4 / svr4_stream.c
blobeb3261c4ef2eee570a0f8aaf37f670571f61f777
1 /* $NetBSD: svr4_stream.c,v 1.76 2008/04/23 13:58:06 ad Exp $ */
3 /*-
4 * Copyright (c) 1994, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Pretend that we have streams...
34 * Yes, this is gross.
36 * ToDo: The state machine for getmsg needs re-thinking
38 * The svr4_32 version is built from this file as well.
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: svr4_stream.c,v 1.76 2008/04/23 13:58:06 ad Exp $");
44 #include <sys/param.h>
45 #include <sys/kernel.h>
46 #include <sys/systm.h>
47 #include <sys/buf.h>
48 #include <sys/malloc.h>
49 #include <sys/ioctl.h>
50 #include <sys/tty.h>
51 #include <sys/file.h>
52 #include <sys/filedesc.h>
53 #include <sys/namei.h>
54 #include <sys/select.h>
55 #include <sys/socket.h>
56 #include <sys/socketvar.h>
57 #include <sys/protosw.h>
58 #include <sys/un.h>
59 #include <net/if.h>
60 #include <netinet/in.h>
61 #include <sys/mbuf.h>
62 #include <sys/mount.h>
63 #include <sys/proc.h>
64 #include <sys/vfs_syscalls.h>
65 #include <sys/vnode.h>
66 #include <sys/device.h>
67 #include <sys/stat.h>
69 #include <sys/syscallargs.h>
71 #ifndef SVR4_32
72 #define compat(name) <compat/svr4/svr4_##name>
73 #else
74 #define compat(name) <compat/svr4_32/svr4_32_##name>
75 #endif
77 #include compat(types.h)
78 #include compat(util.h)
79 #include compat(signal.h)
80 #include compat(lwp.h)
81 #include compat(ucontext.h)
82 #include compat(syscallargs.h)
83 #include compat(stropts.h)
84 #include compat(timod.h)
85 #include <compat/svr4/svr4_sockmod.h>
86 #include compat(ioctl.h)
87 #include compat(socket.h)
89 #undef compat
91 #ifndef SVR4_32
93 #define SCARG_PTR(uap, arg) SCARG(uap, arg)
94 #define NETBSD32PTR(ptr) (ptr)
96 #else
98 #define SCARG_PTR(uap, arg) SCARG_P32(uap, arg)
99 #define NETBSD32PTR(ptr) NETBSD32PTR64(ptr)
101 /* Rename stuff that is different for the svr4_32 build */
102 #define svr4_infocmd svr4_32_infocmd
103 #define svr4_ino_t svr4_32_ino_t
104 #define svr4_netaddr_in svr4_32_netaddr_in
105 #define svr4_netaddr_un svr4_32_netaddr_un
106 #define svr4_strbuf svr4_32_strbuf
107 #define svr4_stream_get svr4_32_stream_get
108 #define svr4_stream_ioctl svr4_32_stream_ioctl
109 #define svr4_stream_ti_ioctl svr4_32_stream_ti_ioctl
110 #define svr4_strfdinsert svr4_32_strfdinsert
111 #define svr4_strioctl svr4_32_strioctl
112 #define svr4_strmcmd svr4_32_strmcmd
113 #define svr4_sys_getmsg svr4_32_sys_getmsg
114 #define svr4_sys_getmsg_args svr4_32_sys_getmsg_args
115 #define svr4_sys_putmsg svr4_32_sys_putmsg
116 #define svr4_sys_putmsg_args svr4_32_sys_putmsg_args
118 #endif /* SVR4_32 */
120 /* Utils */
121 static int clean_pipe(struct lwp *, const char *);
122 static void getparm(file_t *, struct svr4_si_sockparms *);
124 /* Address Conversions */
125 static void sockaddr_to_netaddr_in(struct svr4_strmcmd *,
126 const struct sockaddr_in *);
127 static void sockaddr_to_netaddr_un(struct svr4_strmcmd *,
128 const struct sockaddr_un *);
129 static void netaddr_to_sockaddr_in(struct sockaddr_in *,
130 const struct svr4_strmcmd *);
131 static void netaddr_to_sockaddr_un(struct sockaddr_un *,
132 const struct svr4_strmcmd *);
134 /* stream ioctls */
135 static int i_nread(file_t *, struct lwp *, register_t *, int,
136 u_long, void *);
137 static int i_fdinsert(file_t *, struct lwp *, register_t *, int,
138 u_long, void *);
139 static int i_str(file_t *, struct lwp *, register_t *, int,
140 u_long, void *);
141 static int i_setsig(file_t *, struct lwp *, register_t *, int,
142 u_long, void *);
143 static int i_getsig(file_t *, struct lwp *, register_t *, int,
144 u_long, void *);
145 static int _i_bind_rsvd(file_t *, struct lwp *, register_t *, int,
146 u_long, void *);
147 static int _i_rele_rsvd(file_t *, struct lwp *, register_t *, int,
148 u_long, void *);
150 /* i_str sockmod calls */
151 static int sockmod(file_t *, int, struct svr4_strioctl *,
152 struct lwp *);
153 static int si_listen(file_t *, int, struct svr4_strioctl *,
154 struct lwp *);
155 static int si_ogetudata(file_t *, int, struct svr4_strioctl *,
156 struct lwp *);
157 static int si_sockparams(file_t *, int, struct svr4_strioctl *,
158 struct lwp *);
159 static int si_shutdown(file_t *, int, struct svr4_strioctl *,
160 struct lwp *);
161 static int si_getudata(file_t *, int, struct svr4_strioctl *,
162 struct lwp *);
164 /* i_str timod calls */
165 static int timod(file_t *, int, struct svr4_strioctl *,
166 struct lwp *);
167 static int ti_getinfo(file_t *, int, struct svr4_strioctl *,
168 struct lwp *);
169 static int ti_bind(file_t *, int, struct svr4_strioctl *,
170 struct lwp *);
172 #ifdef DEBUG_SVR4
173 static void bufprint(u_char *, size_t);
174 static int show_ioc(const char *, struct svr4_strioctl *);
175 static int show_strbuf(struct svr4_strbuf *);
176 static void show_msg(const char *, int, struct svr4_strbuf *,
177 struct svr4_strbuf *, int);
179 static void
180 bufprint(u_char *buf, size_t len)
182 size_t i;
184 uprintf("\n\t");
185 for (i = 0; i < len; i++) {
186 uprintf("%x ", buf[i]);
187 if (i && (i % 16) == 0)
188 uprintf("\n\t");
192 static int
193 show_ioc(const char *str, struct svr4_strioctl *ioc)
195 u_char *ptr;
196 int error, len;
198 len = ioc->len;
199 if (len > 1024)
200 len = 1024;
202 ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK);
203 uprintf("%s cmd = %ld, timeout = %d, len = %d, buf = %p { ",
204 str, ioc->cmd, ioc->timeout, ioc->len, ioc->buf);
206 if ((error = copyin(ioc->buf, ptr, len)) != 0) {
207 free((char *) ptr, M_TEMP);
208 return error;
211 bufprint(ptr, len);
213 uprintf("}\n");
215 free((char *) ptr, M_TEMP);
216 return 0;
220 static int
221 show_strbuf(struct svr4_strbuf *str)
223 int error;
224 u_char *ptr = NULL;
225 int maxlen = str->maxlen;
226 int len = str->len;
228 if (maxlen > 8192)
229 maxlen = 8192;
231 if (maxlen < 0)
232 maxlen = 0;
234 if (len >= maxlen)
235 len = maxlen;
237 if (len > 0) {
238 ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK);
240 if ((error = copyin(str->buf, ptr, len)) != 0) {
241 free((char *) ptr, M_TEMP);
242 return error;
246 uprintf(", { %d, %d, %p=[ ", str->maxlen, str->len, str->buf);
248 if (ptr)
249 bufprint(ptr, len);
251 uprintf("]}");
253 if (ptr)
254 free((char *) ptr, M_TEMP);
256 return 0;
260 static void
261 show_msg(const char *str, int fd, struct svr4_strbuf *ctl, struct svr4_strbuf *dat, int flags)
263 struct svr4_strbuf buf;
264 int error;
266 uprintf("%s(%d", str, fd);
267 if (ctl != NULL) {
268 if ((error = copyin(ctl, &buf, sizeof(buf))) != 0)
269 return;
270 show_strbuf(&buf);
272 else
273 uprintf(", NULL");
275 if (dat != NULL) {
276 if ((error = copyin(dat, &buf, sizeof(buf))) != 0)
277 return;
278 show_strbuf(&buf);
280 else
281 uprintf(", NULL");
283 uprintf(", %x);\n", flags);
286 #endif /* DEBUG_SVR4 */
290 * We are faced with an interesting situation. On svr4 unix sockets
291 * are really pipes. But we really have sockets, and we might as
292 * well use them. At the point where svr4 calls TI_BIND, it has
293 * already created a named pipe for the socket using mknod(2).
294 * We need to create a socket with the same name when we bind,
295 * so we need to remove the pipe before, otherwise we'll get address
296 * already in use. So we *carefully* remove the pipe, to avoid
297 * using this as a random file removal tool.
299 static int
300 clean_pipe(struct lwp *l, const char *path)
302 struct nameidata nd;
303 struct vattr va;
304 int error;
306 NDINIT(&nd, DELETE, NOFOLLOW | LOCKPARENT | LOCKLEAF | TRYEMULROOT,
307 UIO_SYSSPACE, path);
309 error = namei(&nd);
310 if (error != 0)
311 return error;
314 * Make sure we are dealing with a mode 0 named pipe.
316 if (nd.ni_vp->v_type != VFIFO)
317 goto bad;
318 error = VOP_GETATTR(nd.ni_vp, &va, l->l_cred);
319 if (error != 0)
320 goto bad;
321 if ((va.va_mode & ALLPERMS) != 0)
322 goto bad;
324 return VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
326 bad:
327 if (nd.ni_dvp == nd.ni_vp)
328 vrele(nd.ni_dvp);
329 else
330 vput(nd.ni_dvp);
331 vput(nd.ni_vp);
332 return error;
336 static void
337 sockaddr_to_netaddr_in(struct svr4_strmcmd *sc, const struct sockaddr_in *sain)
339 struct svr4_netaddr_in *na;
340 na = SVR4_ADDROF(sc);
342 na->family = sain->sin_family;
343 na->port = sain->sin_port;
344 na->addr = sain->sin_addr.s_addr;
345 DPRINTF(("sockaddr_in -> netaddr %d %d %lx\n", na->family, na->port,
346 na->addr));
350 static void
351 sockaddr_to_netaddr_un(struct svr4_strmcmd *sc, const struct sockaddr_un *saun)
353 struct svr4_netaddr_un *na;
354 char *dst, *edst = ((char *) sc) + sc->offs + sizeof(na->family) + 1 -
355 sizeof(*sc);
356 const char *src;
358 na = SVR4_ADDROF(sc);
359 na->family = saun->sun_family;
360 for (src = saun->sun_path, dst = na->path; (*dst++ = *src++) != '\0'; )
361 if (dst == edst)
362 break;
363 DPRINTF(("sockaddr_un -> netaddr %d %s\n", na->family, na->path));
367 static void
368 netaddr_to_sockaddr_in(struct sockaddr_in *sain, const struct svr4_strmcmd *sc)
370 const struct svr4_netaddr_in *na;
373 na = SVR4_C_ADDROF(sc);
374 memset(sain, 0, sizeof(*sain));
375 sain->sin_len = sizeof(*sain);
376 sain->sin_family = na->family;
377 sain->sin_port = na->port;
378 sain->sin_addr.s_addr = na->addr;
379 DPRINTF(("netaddr -> sockaddr_in %d %d %x\n", sain->sin_family,
380 sain->sin_port, sain->sin_addr.s_addr));
384 static void
385 netaddr_to_sockaddr_un(struct sockaddr_un *saun, const struct svr4_strmcmd *sc)
387 const struct svr4_netaddr_un *na;
388 char *dst, *edst = &saun->sun_path[sizeof(saun->sun_path) - 1];
389 const char *src;
391 na = SVR4_C_ADDROF(sc);
392 memset(saun, 0, sizeof(*saun));
393 saun->sun_family = na->family;
394 for (src = na->path, dst = saun->sun_path; (*dst++ = *src++) != '\0'; )
395 if (dst == edst)
396 break;
397 saun->sun_len = dst - saun->sun_path;
398 DPRINTF(("netaddr -> sockaddr_un %d %s\n", saun->sun_family,
399 saun->sun_path));
403 static void
404 getparm(file_t *fp, struct svr4_si_sockparms *pa)
406 struct svr4_strm *st = svr4_stream_get(fp);
407 struct socket *so = (struct socket *) fp->f_data;
409 if (st == NULL)
410 return;
412 pa->family = st->s_family;
414 switch (so->so_type) {
415 case SOCK_DGRAM:
416 pa->type = SVR4_T_CLTS;
417 pa->protocol = IPPROTO_UDP;
418 DPRINTF(("getparm(dgram)\n"));
419 return;
421 case SOCK_STREAM:
422 pa->type = SVR4_T_COTS; /* What about T_COTS_ORD? XXX */
423 pa->protocol = IPPROTO_IP;
424 DPRINTF(("getparm(stream)\n"));
425 return;
427 case SOCK_RAW:
428 pa->type = SVR4_T_CLTS;
429 pa->protocol = IPPROTO_RAW;
430 DPRINTF(("getparm(raw)\n"));
431 return;
433 default:
434 pa->type = 0;
435 pa->protocol = 0;
436 DPRINTF(("getparm(type %d?)\n", so->so_type));
437 return;
442 static int
443 si_ogetudata(file_t *fp, int fd, struct svr4_strioctl *ioc,
444 struct lwp *l)
446 int error;
447 struct svr4_si_oudata ud;
448 struct svr4_si_sockparms pa;
449 (void)memset(&pa, 0, sizeof(pa)); /* XXX: GCC */
451 if (ioc->len != sizeof(ud) && ioc->len != sizeof(ud) - sizeof(int)) {
452 DPRINTF(("SI_OGETUDATA: Wrong size %ld != %d\n",
453 (unsigned long)sizeof(ud), ioc->len));
454 return EINVAL;
457 if ((error = copyin(NETBSD32PTR(ioc->buf), &ud, sizeof(ud))) != 0)
458 return error;
460 getparm(fp, &pa);
462 switch (pa.family) {
463 case AF_INET:
464 ud.tidusize = 16384;
465 ud.addrsize = sizeof(struct sockaddr_in);
466 if (pa.type == SVR4_SOCK_STREAM)
467 ud.etsdusize = 1;
468 else
469 ud.etsdusize = 0;
470 break;
472 case AF_LOCAL:
473 ud.tidusize = 65536;
474 ud.addrsize = 128;
475 ud.etsdusize = 128;
476 break;
478 default:
479 DPRINTF(("SI_OGETUDATA: Unsupported address family %d\n",
480 pa.family));
481 return ENOSYS;
484 /* I have no idea what these should be! */
485 ud.optsize = 128;
486 ud.tsdusize = 128;
488 ud.servtype = pa.type;
490 /* XXX: Fixme */
491 ud.so_state = 0;
492 ud.so_options = 0;
493 return copyout(&ud, NETBSD32PTR(ioc->buf), ioc->len);
497 static int
498 si_sockparams(file_t *fp, int fd, struct svr4_strioctl *ioc,
499 struct lwp *l)
501 struct svr4_si_sockparms pa;
503 getparm(fp, &pa);
504 return copyout(&pa, NETBSD32PTR(ioc->buf), sizeof(pa));
508 static int
509 si_listen(file_t *fp, int fd, struct svr4_strioctl *ioc, struct lwp *l)
511 int error;
512 struct svr4_strm *st = svr4_stream_get(fp);
513 register_t retval;
514 struct svr4_strmcmd lst;
515 struct sys_listen_args la;
517 if (st == NULL)
518 return EINVAL;
520 if (ioc->len > sizeof(lst))
521 return EINVAL;
523 if ((error = copyin(NETBSD32PTR(ioc->buf), &lst, ioc->len)) != 0)
524 return error;
526 if (lst.cmd != SVR4_TI_OLD_BIND_REQUEST) {
527 DPRINTF(("si_listen: bad request %ld\n", lst.cmd));
528 return EINVAL;
532 * We are making assumptions again...
534 SCARG(&la, s) = fd;
535 DPRINTF(("SI_LISTEN: fileno %d backlog = %d\n", fd, 5));
536 SCARG(&la, backlog) = 5;
538 if ((error = sys_listen(l, &la, &retval)) != 0) {
539 DPRINTF(("SI_LISTEN: listen failed %d\n", error));
540 return error;
543 st->s_cmd = SVR4_TI__ACCEPT_WAIT;
544 lst.cmd = SVR4_TI_BIND_REPLY;
546 switch (st->s_family) {
547 case AF_INET:
548 /* XXX: Fill the length here */
549 break;
551 case AF_LOCAL:
552 lst.len = 140;
553 lst.pad[28] = 0x00000000; /* magic again */
554 lst.pad[29] = 0x00000800; /* magic again */
555 lst.pad[30] = 0x80001400; /* magic again */
556 break;
558 default:
559 DPRINTF(("SI_LISTEN: Unsupported address family %d\n",
560 st->s_family));
561 return ENOSYS;
565 if ((error = copyout(&lst, NETBSD32PTR(ioc->buf), ioc->len)) != 0)
566 return error;
568 return 0;
572 static int
573 si_getudata(file_t *fp, int fd, struct svr4_strioctl *ioc,
574 struct lwp *l)
576 int error;
577 struct svr4_si_udata ud;
579 if (sizeof(ud) != ioc->len) {
580 DPRINTF(("SI_GETUDATA: Wrong size %ld != %d\n",
581 (unsigned long)sizeof(ud), ioc->len));
582 return EINVAL;
585 if ((error = copyin(NETBSD32PTR(ioc->buf), &ud, sizeof(ud))) != 0)
586 return error;
588 getparm(fp, &ud.sockparms);
590 switch (ud.sockparms.family) {
591 case AF_INET:
592 ud.tidusize = 16384;
593 ud.tsdusize = 16384;
594 ud.addrsize = sizeof(struct sockaddr_in);
595 if (ud.sockparms.type == SVR4_SOCK_STREAM)
596 ud.etsdusize = 1;
597 else
598 ud.etsdusize = 0;
599 ud.optsize = 0;
600 break;
602 case AF_LOCAL:
603 ud.tidusize = 65536;
604 ud.tsdusize = 128;
605 ud.addrsize = 128;
606 ud.etsdusize = 128;
607 ud.optsize = 128;
608 break;
610 default:
611 DPRINTF(("SI_GETUDATA: Unsupported address family %d\n",
612 ud.sockparms.family));
613 return ENOSYS;
617 ud.servtype = ud.sockparms.type;
619 /* XXX: Fixme */
620 ud.so_state = 0;
621 ud.so_options = 0;
622 return copyout(&ud, NETBSD32PTR(ioc->buf), sizeof(ud));
626 static int
627 si_shutdown(file_t *fp, int fd, struct svr4_strioctl *ioc,
628 struct lwp *l)
630 int error;
631 struct sys_shutdown_args ap;
632 register_t retval;
634 if (ioc->len != sizeof(SCARG(&ap, how))) {
635 DPRINTF(("SI_SHUTDOWN: Wrong size %ld != %d\n",
636 (unsigned long)sizeof(SCARG(&ap, how)), ioc->len));
637 return EINVAL;
640 if ((error = copyin(NETBSD32PTR(ioc->buf), &SCARG(&ap, how), ioc->len)) != 0)
641 return error;
643 SCARG(&ap, s) = fd;
645 return sys_shutdown(l, &ap, &retval);
649 static int
650 sockmod(file_t *fp, int fd, struct svr4_strioctl *ioc, struct lwp *l)
652 switch (ioc->cmd) {
653 case SVR4_SI_OGETUDATA:
654 DPRINTF(("SI_OGETUDATA\n"));
655 return si_ogetudata(fp, fd, ioc, l);
657 case SVR4_SI_SHUTDOWN:
658 DPRINTF(("SI_SHUTDOWN\n"));
659 return si_shutdown(fp, fd, ioc, l);
661 case SVR4_SI_LISTEN:
662 DPRINTF(("SI_LISTEN\n"));
663 return si_listen(fp, fd, ioc, l);
665 case SVR4_SI_SETMYNAME:
666 DPRINTF(("SI_SETMYNAME\n"));
667 return 0;
669 case SVR4_SI_SETPEERNAME:
670 DPRINTF(("SI_SETPEERNAME\n"));
671 return 0;
673 case SVR4_SI_GETINTRANSIT:
674 DPRINTF(("SI_GETINTRANSIT\n"));
675 return 0;
677 case SVR4_SI_TCL_LINK:
678 DPRINTF(("SI_TCL_LINK\n"));
679 return 0;
681 case SVR4_SI_TCL_UNLINK:
682 DPRINTF(("SI_TCL_UNLINK\n"));
683 return 0;
685 case SVR4_SI_SOCKPARAMS:
686 DPRINTF(("SI_SOCKPARAMS\n"));
687 return si_sockparams(fp, fd, ioc, l);
689 case SVR4_SI_GETUDATA:
690 DPRINTF(("SI_GETUDATA\n"));
691 return si_getudata(fp, fd, ioc, l);
693 default:
694 DPRINTF(("Unknown sockmod ioctl %lx\n", ioc->cmd));
695 return 0;
701 static int
702 ti_getinfo(file_t *fp, int fd, struct svr4_strioctl *ioc,
703 struct lwp *l)
705 int error;
706 struct svr4_infocmd info;
708 memset(&info, 0, sizeof(info));
710 if (ioc->len > sizeof(info))
711 return EINVAL;
713 if ((error = copyin(NETBSD32PTR(ioc->buf), &info, ioc->len)) != 0)
714 return error;
716 if (info.cmd != SVR4_TI_INFO_REQUEST)
717 return EINVAL;
719 info.cmd = SVR4_TI_INFO_REPLY;
720 info.tsdu = 0;
721 info.etsdu = 1;
722 info.cdata = -2;
723 info.ddata = -2;
724 info.addr = 16;
725 info.opt = -1;
726 info.tidu = 16384;
727 info.serv = 2;
728 info.current = 0;
729 info.provider = 2;
731 ioc->len = sizeof(info);
732 if ((error = copyout(&info, NETBSD32PTR(ioc->buf), ioc->len)) != 0)
733 return error;
735 return 0;
739 static int
740 ti_bind(file_t *fp, int fd, struct svr4_strioctl *ioc, struct lwp *l)
742 int error;
743 struct svr4_strm *st = svr4_stream_get(fp);
744 struct sockaddr_in sain;
745 struct sockaddr_un saun;
746 void *skp, *sup = NULL;
747 int sasize;
748 struct svr4_strmcmd bnd;
749 struct mbuf *name;
751 if (st == NULL) {
752 DPRINTF(("ti_bind: bad file descriptor\n"));
753 return EINVAL;
756 if (ioc->len > sizeof(bnd))
757 return EINVAL;
759 if ((error = copyin(NETBSD32PTR(ioc->buf), &bnd, ioc->len)) != 0)
760 return error;
762 if (bnd.cmd != SVR4_TI_OLD_BIND_REQUEST) {
763 DPRINTF(("ti_bind: bad request %ld\n", bnd.cmd));
764 return EINVAL;
767 switch (st->s_family) {
768 case AF_INET:
769 skp = &sain;
770 sasize = sizeof(sain);
772 if (bnd.offs == 0)
773 goto reply;
775 netaddr_to_sockaddr_in(&sain, &bnd);
777 DPRINTF(("TI_BIND: fam %d, port %d, addr %x\n",
778 sain.sin_family, sain.sin_port,
779 sain.sin_addr.s_addr));
780 break;
782 case AF_LOCAL:
783 skp = &saun;
784 sasize = sizeof(saun);
785 if (bnd.offs == 0)
786 goto reply;
788 netaddr_to_sockaddr_un(&saun, &bnd);
790 if (saun.sun_path[0] == '\0')
791 goto reply;
793 DPRINTF(("TI_BIND: fam %d, path %s\n",
794 saun.sun_family, saun.sun_path));
796 if ((error = clean_pipe(l, saun.sun_path)) != 0)
797 return error;
799 bnd.pad[28] = 0x00001000; /* magic again */
800 break;
802 default:
803 DPRINTF(("TI_BIND: Unsupported address family %d\n",
804 st->s_family));
805 return ENOSYS;
808 name = m_get(M_WAIT, MT_SONAME);
809 if (sasize > MLEN)
810 MEXTMALLOC(name, sasize, M_WAITOK);
812 memcpy(mtod(name, void *), skp, sasize);
814 DPRINTF(("TI_BIND: fileno %d\n", fd));
816 error = do_sys_bind(l, fd, name);
817 if (error != 0) {
818 DPRINTF(("TI_BIND: bind failed %d\n", error));
819 return error;
822 reply:
823 if (sup == NULL) {
824 memset(&bnd, 0, sizeof(bnd));
825 bnd.len = sasize + 4;
826 bnd.offs = 0x10; /* XXX */
829 bnd.cmd = SVR4_TI_BIND_REPLY;
831 if ((error = copyout(&bnd, NETBSD32PTR(ioc->buf), ioc->len)) != 0)
832 return error;
834 return 0;
838 static int
839 timod(file_t *fp, int fd, struct svr4_strioctl *ioc, struct lwp *l)
841 switch (ioc->cmd) {
842 case SVR4_TI_GETINFO:
843 DPRINTF(("TI_GETINFO\n"));
844 return ti_getinfo(fp, fd, ioc, l);
846 case SVR4_TI_OPTMGMT:
847 DPRINTF(("TI_OPTMGMT\n"));
848 return 0;
850 case SVR4_TI_BIND:
851 DPRINTF(("TI_BIND\n"));
852 return ti_bind(fp, fd, ioc, l);
854 case SVR4_TI_UNBIND:
855 DPRINTF(("TI_UNBIND\n"));
856 return 0;
858 default:
859 DPRINTF(("Unknown timod ioctl %lx\n", ioc->cmd));
860 return 0;
866 svr4_stream_ti_ioctl(file_t *fp, struct lwp *l, register_t *retval, int fd, u_long cmd, void *dat)
868 struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat;
869 struct svr4_strm *st = svr4_stream_get(fp);
870 int error;
871 struct svr4_strmcmd sc;
872 struct mbuf *name;
874 if (st == NULL)
875 return EINVAL;
877 sc.offs = 0x10;
879 if ((error = copyin(sub, &skb, sizeof(skb))) != 0) {
880 DPRINTF(("ti_ioctl: error copying in strbuf\n"));
881 return error;
884 switch (cmd) {
885 case SVR4_TI_GETMYNAME:
886 DPRINTF(("TI_GETMYNAME\n"));
887 cmd = PRU_SOCKADDR;
888 break;
890 case SVR4_TI_GETPEERNAME:
891 DPRINTF(("TI_GETPEERNAME\n"));
892 cmd = PRU_PEERADDR;
893 break;
895 case SVR4_TI_SETMYNAME:
896 DPRINTF(("TI_SETMYNAME\n"));
897 return 0;
899 case SVR4_TI_SETPEERNAME:
900 DPRINTF(("TI_SETPEERNAME\n"));
901 return 0;
902 default:
903 DPRINTF(("ti_ioctl: Unknown ioctl %lx\n", cmd));
904 return ENOSYS;
907 error = do_sys_getsockname(l, fd, cmd, &name);
908 if (error != 0)
909 return error;
911 switch (st->s_family) {
912 case AF_INET:
913 sockaddr_to_netaddr_in(&sc, mtod(name, void *));
914 skb.len = sizeof (struct sockaddr_in);
915 break;
917 case AF_LOCAL:
918 sockaddr_to_netaddr_un(&sc, mtod(name, void *));
919 /* XXX: the length gets adjusted but the copyout doesn't */
920 skb.len = sizeof (struct sockaddr_un) + 4;
921 break;
923 default:
924 DPRINTF(("ti_ioctl: Unsupported address family %d\n",
925 st->s_family));
926 m_free(name);
927 return ENOSYS;
930 error = copyout(SVR4_ADDROF(&sc), NETBSD32PTR(skb.buf), name->m_len);
931 m_free(name);
932 if (error != 0) {
933 DPRINTF(("ti_ioctl: error copying out socket data\n"));
934 return error;
938 if ((error = copyout(&skb, sub, sizeof(skb))) != 0) {
939 DPRINTF(("ti_ioctl: error copying out strbuf\n"));
940 return error;
943 return error;
949 static int
950 i_nread(file_t *fp, struct lwp *l, register_t *retval, int fd,
951 u_long cmd, void *dat)
953 int error;
954 int nread = 0;
957 * We are supposed to return the message length in nread, and the
958 * number of messages in retval. We don't have the notion of number
959 * of stream messages, so we just find out if we have any bytes waiting
960 * for us, and if we do, then we assume that we have at least one
961 * message waiting for us.
963 if ((error = (*fp->f_ops->fo_ioctl)(fp, FIONREAD, &nread)) != 0)
964 return error;
966 if (nread != 0)
967 *retval = 1;
968 else
969 *retval = 0;
971 return copyout(&nread, dat, sizeof(nread));
974 static int
975 i_fdinsert(file_t *fp, struct lwp *l, register_t *retval, int fd,
976 u_long cmd, void *dat)
979 * Major hack again here. We assume that we are using this to
980 * implement accept(2). If that is the case, we have already
981 * called accept, and we have stored the file descriptor in
982 * afd. We find the file descriptor that the code wants to use
983 * in fd insert, and then we dup2() our accepted file descriptor
984 * to it.
986 int error;
987 struct svr4_strm *st = svr4_stream_get(fp);
988 struct svr4_strfdinsert fdi;
989 struct sys_dup2_args d2p;
990 struct sys_close_args clp;
992 if (st == NULL) {
993 DPRINTF(("fdinsert: bad file type\n"));
994 return EINVAL;
997 if (st->s_afd == -1) {
998 DPRINTF(("fdinsert: accept fd not found\n"));
999 return ENOENT;
1002 if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) {
1003 DPRINTF(("fdinsert: copyin failed %d\n", error));
1004 return error;
1007 SCARG(&d2p, from) = st->s_afd;
1008 SCARG(&d2p, to) = fdi.fd;
1010 if ((error = sys_dup2(l, &d2p, retval)) != 0) {
1011 DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n",
1012 st->s_afd, fdi.fd, error));
1013 return error;
1016 SCARG(&clp, fd) = st->s_afd;
1018 if ((error = sys_close(l, &clp, retval)) != 0) {
1019 DPRINTF(("fdinsert: close(%d) failed %d\n",
1020 st->s_afd, error));
1021 return error;
1024 st->s_afd = -1;
1026 *retval = 0;
1027 return 0;
1031 static int
1032 _i_bind_rsvd(file_t *fp, struct lwp *l, register_t *retval,
1033 int fd, u_long cmd, void *dat)
1035 struct sys_mkfifo_args ap;
1038 * This is a supposed to be a kernel and library only ioctl.
1039 * It gets called before ti_bind, when we have a unix
1040 * socket, to physically create the socket transport and
1041 * ``reserve'' it. I don't know how this get reserved inside
1042 * the kernel, but we are going to create it nevertheless.
1044 SCARG(&ap, path) = dat;
1045 SCARG(&ap, mode) = S_IFIFO;
1047 return sys_mkfifo(l, &ap, retval);
1050 static int
1051 _i_rele_rsvd(file_t *fp, struct lwp *l, register_t *retval,
1052 int fd, u_long cmd, void *dat)
1054 struct sys_unlink_args ap;
1057 * This is a supposed to be a kernel and library only ioctl.
1058 * I guess it is supposed to release the socket.
1060 SCARG(&ap, path) = dat;
1062 return sys_unlink(l, &ap, retval);
1065 static int
1066 i_str(file_t *fp, struct lwp *l, register_t *retval, int fd,
1067 u_long cmd, void *dat)
1069 int error;
1070 struct svr4_strioctl ioc;
1073 * Noop on non sockets
1075 if (fp->f_type != DTYPE_SOCKET)
1076 return 0;
1078 if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0)
1079 return error;
1081 #ifdef DEBUG_SVR4
1082 if ((error = show_ioc(">", &ioc)) != 0)
1083 return error;
1084 #endif /* DEBUG_SVR4 */
1086 switch (ioc.cmd & 0xff00) {
1087 case SVR4_SIMOD:
1088 if ((error = sockmod(fp, fd, &ioc, l)) != 0)
1089 return error;
1090 break;
1092 case SVR4_TIMOD:
1093 if ((error = timod(fp, fd, &ioc, l)) != 0)
1094 return error;
1095 break;
1097 default:
1098 DPRINTF(("Unimplemented module %c %ld\n",
1099 (char) (cmd >> 8), cmd & 0xff));
1100 return 0;
1103 #ifdef DEBUG_SVR4
1104 if ((error = show_ioc("<", &ioc)) != 0)
1105 return error;
1106 #endif /* DEBUG_SVR4 */
1107 return copyout(&ioc, dat, sizeof(ioc));
1110 static int
1111 i_setsig(file_t *fp, struct lwp *l, register_t *retval, int fd,
1112 u_long cmd, void *dat)
1115 * This is the best we can do for now; we cannot generate
1116 * signals only for specific events so the signal mask gets
1117 * ignored; we save it just to pass it to a possible I_GETSIG...
1119 * We alse have to fix the O_ASYNC fcntl bit, so the
1120 * process will get SIGPOLLs.
1122 struct sys_fcntl_args fa;
1123 int error;
1124 register_t oflags, flags;
1125 struct svr4_strm *st = svr4_stream_get(fp);
1127 if (st == NULL) {
1128 DPRINTF(("i_setsig: bad file descriptor\n"));
1129 return EINVAL;
1131 /* get old status flags */
1132 SCARG(&fa, fd) = fd;
1133 SCARG(&fa, cmd) = F_GETFL;
1135 if ((error = sys_fcntl(l, &fa, &oflags)) != 0)
1136 return error;
1138 /* update the flags */
1139 if (dat != NULL) {
1140 int mask;
1142 flags = oflags | O_ASYNC;
1143 mask = (int)(u_long)dat;
1144 if (mask & ~SVR4_S_ALLMASK) {
1145 DPRINTF(("i_setsig: bad eventmask data %x\n", mask));
1146 return EINVAL;
1148 st->s_eventmask = mask;
1150 else {
1151 flags = oflags & ~O_ASYNC;
1152 st->s_eventmask = 0;
1155 /* set the new flags, if changed */
1156 if (flags != oflags) {
1157 SCARG(&fa, cmd) = F_SETFL;
1158 SCARG(&fa, arg) = (void *) flags;
1159 if ((error = sys_fcntl(l, &fa, &flags)) != 0)
1160 return error;
1163 /* set up SIGIO receiver if needed */
1164 if (dat != NULL) {
1165 SCARG(&fa, cmd) = F_SETOWN;
1166 SCARG(&fa, arg) = (void *)(u_long)l->l_proc->p_pid;
1167 return sys_fcntl(l, &fa, &flags);
1169 return 0;
1172 static int
1173 i_getsig(file_t *fp, struct lwp *l, register_t *retval,
1174 int fd, u_long cmd, void *dat)
1176 int error;
1178 if (dat != NULL) {
1179 struct svr4_strm *st = svr4_stream_get(fp);
1181 if (st == NULL) {
1182 DPRINTF(("i_getsig: bad file descriptor\n"));
1183 return EINVAL;
1185 if ((error = copyout(&st->s_eventmask, dat,
1186 sizeof(st->s_eventmask))) != 0) {
1187 DPRINTF(("i_getsig: bad eventmask pointer\n"));
1188 return error;
1191 return 0;
1195 svr4_stream_ioctl(file_t *fp, struct lwp *l, register_t *retval, int fd, u_long cmd, void *dat)
1197 *retval = 0;
1200 * All the following stuff assumes "sockmod" is pushed...
1202 switch (cmd) {
1203 case SVR4_I_NREAD:
1204 DPRINTF(("I_NREAD\n"));
1205 return i_nread(fp, l, retval, fd, cmd, dat);
1207 case SVR4_I_PUSH:
1208 DPRINTF(("I_PUSH\n"));
1209 return 0;
1211 case SVR4_I_POP:
1212 DPRINTF(("I_POP\n"));
1213 return 0;
1215 case SVR4_I_LOOK:
1216 DPRINTF(("I_LOOK\n"));
1217 return 0;
1219 case SVR4_I_FLUSH:
1220 DPRINTF(("I_FLUSH\n"));
1221 return 0;
1223 case SVR4_I_SRDOPT:
1224 DPRINTF(("I_SRDOPT\n"));
1225 return 0;
1227 case SVR4_I_GRDOPT:
1228 DPRINTF(("I_GRDOPT\n"));
1229 return 0;
1231 case SVR4_I_STR:
1232 DPRINTF(("I_STR\n"));
1233 return i_str(fp, l, retval, fd, cmd, dat);
1235 case SVR4_I_SETSIG:
1236 DPRINTF(("I_SETSIG\n"));
1237 return i_setsig(fp, l, retval, fd, cmd, dat);
1239 case SVR4_I_GETSIG:
1240 DPRINTF(("I_GETSIG\n"));
1241 return i_getsig(fp, l, retval, fd, cmd, dat);
1243 case SVR4_I_FIND:
1244 DPRINTF(("I_FIND\n"));
1246 * Here we are not pushing modules really, we just
1247 * pretend all are present
1249 *retval = 1;
1250 return 0;
1252 case SVR4_I_LINK:
1253 DPRINTF(("I_LINK\n"));
1254 return 0;
1256 case SVR4_I_UNLINK:
1257 DPRINTF(("I_UNLINK\n"));
1258 return 0;
1260 case SVR4_I_ERECVFD:
1261 DPRINTF(("I_ERECVFD\n"));
1262 return 0;
1264 case SVR4_I_PEEK:
1265 DPRINTF(("I_PEEK\n"));
1266 return 0;
1268 case SVR4_I_FDINSERT:
1269 DPRINTF(("I_FDINSERT\n"));
1270 return i_fdinsert(fp, l, retval, fd, cmd, dat);
1272 case SVR4_I_SENDFD:
1273 DPRINTF(("I_SENDFD\n"));
1274 return 0;
1276 case SVR4_I_RECVFD:
1277 DPRINTF(("I_RECVFD\n"));
1278 return 0;
1280 case SVR4_I_SWROPT:
1281 DPRINTF(("I_SWROPT\n"));
1282 return 0;
1284 case SVR4_I_GWROPT:
1285 DPRINTF(("I_GWROPT\n"));
1286 return 0;
1288 case SVR4_I_LIST:
1289 DPRINTF(("I_LIST\n"));
1290 return 0;
1292 case SVR4_I_PLINK:
1293 DPRINTF(("I_PLINK\n"));
1294 return 0;
1296 case SVR4_I_PUNLINK:
1297 DPRINTF(("I_PUNLINK\n"));
1298 return 0;
1300 case SVR4_I_SETEV:
1301 DPRINTF(("I_SETEV\n"));
1302 return 0;
1304 case SVR4_I_GETEV:
1305 DPRINTF(("I_GETEV\n"));
1306 return 0;
1308 case SVR4_I_STREV:
1309 DPRINTF(("I_STREV\n"));
1310 return 0;
1312 case SVR4_I_UNSTREV:
1313 DPRINTF(("I_UNSTREV\n"));
1314 return 0;
1316 case SVR4_I_FLUSHBAND:
1317 DPRINTF(("I_FLUSHBAND\n"));
1318 return 0;
1320 case SVR4_I_CKBAND:
1321 DPRINTF(("I_CKBAND\n"));
1322 return 0;
1324 case SVR4_I_GETBAND:
1325 DPRINTF(("I_GETBANK\n"));
1326 return 0;
1328 case SVR4_I_ATMARK:
1329 DPRINTF(("I_ATMARK\n"));
1330 return 0;
1332 case SVR4_I_SETCLTIME:
1333 DPRINTF(("I_SETCLTIME\n"));
1334 return 0;
1336 case SVR4_I_GETCLTIME:
1337 DPRINTF(("I_GETCLTIME\n"));
1338 return 0;
1340 case SVR4_I_CANPUT:
1341 DPRINTF(("I_CANPUT\n"));
1342 return 0;
1344 case SVR4__I_BIND_RSVD:
1345 DPRINTF(("_I_BIND_RSVD\n"));
1346 return _i_bind_rsvd(fp, l, retval, fd, cmd, dat);
1348 case SVR4__I_RELE_RSVD:
1349 DPRINTF(("_I_RELE_RSVD\n"));
1350 return _i_rele_rsvd(fp, l, retval, fd, cmd, dat);
1352 default:
1353 DPRINTF(("unimpl cmd = %lx\n", cmd));
1354 break;
1357 return 0;
1364 svr4_sys_putmsg(struct lwp *l, const struct svr4_sys_putmsg_args *uap, register_t *retval)
1366 struct proc *p = l->l_proc;
1367 file_t *fp;
1368 struct svr4_strbuf dat, ctl;
1369 struct svr4_strmcmd sc;
1370 struct sockaddr_in sain;
1371 struct sockaddr_un saun;
1372 void *skp;
1373 int sasize;
1374 struct svr4_strm *st;
1375 int error;
1376 struct mbuf *nam;
1377 struct msghdr msg;
1378 struct iovec aiov;
1381 #ifdef DEBUG_SVR4
1382 show_msg(">putmsg", SCARG(uap, fd), SCARG(uap, ctl),
1383 SCARG(uap, dat), SCARG(uap, flags));
1384 #endif /* DEBUG_SVR4 */
1386 if ((fp = fd_getfile(SCARG(uap, fd))) == NULL)
1387 return EBADF;
1389 KERNEL_LOCK(1, NULL); /* svr4_find_socket */
1391 if (SCARG_PTR(uap, ctl) != NULL) {
1392 if ((error = copyin(SCARG_PTR(uap, ctl),
1393 &ctl, sizeof(ctl))) != 0)
1394 goto out;
1395 } else
1396 ctl.len = -1;
1398 if (SCARG_PTR(uap, dat) != NULL) {
1399 if ((error = copyin(SCARG_PTR(uap, dat),
1400 &dat, sizeof(dat))) != 0)
1401 goto out;
1402 } else
1403 dat.len = -1;
1406 * Only for sockets for now.
1408 if ((st = svr4_stream_get(fp)) == NULL) {
1409 DPRINTF(("putmsg: bad file type\n"));
1410 error = EINVAL;
1411 goto out;
1414 if (ctl.len > sizeof(sc)) {
1415 DPRINTF(("putmsg: Bad control size %ld != %d\n",
1416 (unsigned long)sizeof(struct svr4_strmcmd), ctl.len));
1417 error = EINVAL;
1418 goto out;
1421 if ((error = copyin(NETBSD32PTR(ctl.buf), &sc, ctl.len)) != 0)
1422 goto out;
1424 switch (st->s_family) {
1425 case AF_INET:
1426 if (sc.len != sizeof(sain)) {
1427 #ifdef notyet
1428 if (sc.cmd == SVR4_TI_DATA_REQUEST) {
1429 struct sys_write_args wa;
1431 /* Solaris seems to use sc.cmd = 3 to
1432 * send "expedited" data. telnet uses
1433 * this for options processing, sending EOF,
1434 * etc. I'm sure other things use it too.
1435 * I don't have any documentation
1436 * on it, so I'm making a guess that this
1437 * is how it works. newton@atdot.dotat.org XXX
1439 * Hmm, expedited data seems to be sc.cmd = 4.
1440 * I think 3 is normal data. (christos)
1442 DPRINTF(("sending expedited data (?)\n"));
1443 SCARG(&wa, fd) = SCARG(uap, fd);
1444 SCARG(&wa, buf) = dat.buf;
1445 SCARG(&wa, nbyte) = dat.len;
1446 error = sys_write(l, &wa, retval);
1447 goto out;
1449 #endif
1450 DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len));
1451 error = EINVAL;
1452 goto out;
1454 netaddr_to_sockaddr_in(&sain, &sc);
1455 skp = &sain;
1456 sasize = sizeof(sain);
1457 error = sain.sin_family != st->s_family;
1458 break;
1460 case AF_LOCAL:
1461 if (ctl.len == 8) {
1462 /* We are doing an accept; succeed */
1463 DPRINTF(("putmsg: Do nothing\n"));
1464 *retval = 0;
1465 error = 0;
1466 goto out;
1468 else {
1469 /* Maybe we've been given a device/inode pair */
1470 dev_t *dev = SVR4_ADDROF(&sc);
1471 svr4_ino_t *ino = (svr4_ino_t *) &dev[1];
1472 skp = svr4_find_socket(p, fp, *dev, *ino);
1473 if (skp == NULL) {
1474 skp = &saun;
1475 /* I guess we have it by name */
1476 netaddr_to_sockaddr_un(skp, &sc);
1478 sasize = sizeof(saun);
1480 break;
1482 default:
1483 DPRINTF(("putmsg: Unsupported address family %d\n",
1484 st->s_family));
1485 error = ENOSYS;
1486 goto out;
1489 nam = m_get(M_WAIT, MT_SONAME);
1490 nam->m_len = sasize;
1491 memcpy(mtod(nam, void *), skp, sasize);
1493 switch (st->s_cmd = sc.cmd) {
1494 case SVR4_TI_CONNECT_REQUEST: /* connect */
1495 KERNEL_UNLOCK_ONE(NULL);
1496 return do_sys_connect(l, SCARG(uap, fd), nam);
1498 case SVR4_TI_SENDTO_REQUEST: /* sendto */
1499 KERNEL_UNLOCK_ONE(NULL);
1500 msg.msg_name = nam;
1501 msg.msg_namelen = sasize;
1502 msg.msg_iov = &aiov;
1503 msg.msg_iovlen = 1;
1504 msg.msg_control = NULL;
1505 msg.msg_flags = MSG_NAMEMBUF;
1506 aiov.iov_base = NETBSD32PTR(dat.buf);
1507 aiov.iov_len = dat.len;
1508 error = do_sys_sendmsg(l, SCARG(uap, fd), &msg,
1509 SCARG(uap, flags), retval);
1511 *retval = 0;
1512 return error;
1514 default:
1515 m_free(nam);
1516 DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd));
1517 error = ENOSYS;
1518 goto out;
1521 out:
1522 KERNEL_UNLOCK_ONE(NULL);
1523 fd_putfile(SCARG(uap, fd));
1524 return error;
1529 svr4_sys_getmsg(struct lwp *l, const struct svr4_sys_getmsg_args *uap, register_t *retval)
1531 file_t *fp;
1532 struct svr4_strbuf dat, ctl;
1533 struct svr4_strmcmd sc;
1534 int error = 0;
1535 struct msghdr msg;
1536 struct iovec aiov;
1537 struct svr4_strm *st;
1538 int fl;
1539 struct mbuf *name;
1541 memset(&sc, 0, sizeof(sc));
1543 #ifdef DEBUG_SVR4
1544 show_msg(">getmsg", SCARG(uap, fd), SCARG(uap, ctl),
1545 SCARG(uap, dat), 0);
1546 #endif /* DEBUG_SVR4 */
1548 if ((fp = fd_getfile(SCARG(uap, fd))) == NULL)
1549 return EBADF;
1551 if (SCARG_PTR(uap, ctl) != NULL) {
1552 if ((error = copyin(SCARG_PTR(uap, ctl), &ctl,
1553 sizeof(ctl))) != 0)
1554 goto out;
1555 } else {
1556 ctl.len = -1;
1557 ctl.maxlen = 0;
1560 if (SCARG_PTR(uap, dat) != NULL) {
1561 if ((error = copyin(SCARG_PTR(uap, dat), &dat,
1562 sizeof(dat))) != 0)
1563 goto out;
1564 } else {
1565 dat.len = -1;
1566 dat.maxlen = 0;
1570 * Only for sockets for now.
1572 if ((st = svr4_stream_get(fp)) == NULL) {
1573 DPRINTF(("getmsg: bad file type\n"));
1574 error = EINVAL;
1575 goto out;
1578 if (ctl.maxlen == -1 || dat.maxlen == -1) {
1579 DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n"));
1580 error = ENOSYS;
1581 goto out;
1584 switch (st->s_family) {
1585 case AF_INET:
1586 case AF_LOCAL:
1587 break;
1589 default:
1590 DPRINTF(("getmsg: Unsupported address family %d\n",
1591 st->s_family));
1592 goto out;
1595 switch (st->s_cmd) {
1596 case SVR4_TI_CONNECT_REQUEST:
1597 DPRINTF(("getmsg: TI_CONNECT_REQUEST\n"));
1599 * We do the connect in one step, so the putmsg should
1600 * have gotten the error.
1602 sc.cmd = SVR4_TI_OK_REPLY;
1603 sc.len = 0;
1605 ctl.len = 8;
1606 dat.len = -1;
1607 fl = 1;
1608 st->s_cmd = sc.cmd;
1609 break;
1611 case SVR4_TI_OK_REPLY:
1612 DPRINTF(("getmsg: TI_OK_REPLY\n"));
1614 * We are immediately after a connect reply, so we send
1615 * a connect verification.
1618 error = do_sys_getsockname(l, SCARG(uap, fd), PRU_SOCKADDR,
1619 &name);
1620 if (error != 0) {
1621 DPRINTF(("getmsg: getpeername failed %d\n", error));
1622 goto out;
1625 sc.cmd = SVR4_TI_CONNECT_REPLY;
1626 sc.pad[0] = 0x4;
1627 sc.offs = 0x18;
1628 sc.pad[1] = 0x14;
1629 sc.pad[2] = 0x04000402;
1631 switch (st->s_family) {
1632 case AF_INET:
1633 sc.len = sizeof (struct sockaddr_in) + 4;
1634 sockaddr_to_netaddr_in(&sc, mtod(name, void *));
1635 break;
1637 case AF_LOCAL:
1638 sc.len = sizeof (struct sockaddr_un) + 4;
1639 sockaddr_to_netaddr_un(&sc, mtod(name, void *));
1640 break;
1642 default:
1643 m_free(name);
1644 error = ENOSYS;
1645 goto out;
1647 m_free(name);
1649 ctl.len = 40;
1650 dat.len = -1;
1651 fl = 0;
1652 st->s_cmd = sc.cmd;
1653 break;
1655 case SVR4_TI__ACCEPT_OK:
1656 DPRINTF(("getmsg: TI__ACCEPT_OK\n"));
1658 * We do the connect in one step, so the putmsg should
1659 * have gotten the error.
1661 sc.cmd = SVR4_TI_OK_REPLY;
1662 sc.len = 1;
1664 ctl.len = 8;
1665 dat.len = -1;
1666 fl = 1;
1667 st->s_cmd = SVR4_TI__ACCEPT_WAIT;
1668 break;
1670 case SVR4_TI__ACCEPT_WAIT:
1671 DPRINTF(("getmsg: TI__ACCEPT_WAIT\n"));
1673 * We are after a listen, so we try to accept...
1676 error = do_sys_accept(l, SCARG(uap, fd), &name, retval);
1677 if (error != 0) {
1678 DPRINTF(("getmsg: accept failed %d\n", error));
1679 goto out;
1682 st->s_afd = *retval;
1684 DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd));
1686 sc.cmd = SVR4_TI_ACCEPT_REPLY;
1687 sc.offs = 0x18;
1688 sc.pad[0] = 0x0;
1690 switch (st->s_family) {
1691 case AF_INET:
1692 sc.pad[1] = 0x28;
1693 sockaddr_to_netaddr_in(&sc, mtod(name, void *));
1694 ctl.len = 40;
1695 sc.len = sizeof (struct sockaddr_in);
1696 break;
1698 case AF_LOCAL:
1699 sc.pad[1] = 0x00010000;
1700 sc.pad[2] = 0xf6bcdaa0; /* I don't know what that is */
1701 sc.pad[3] = 0x00010000;
1702 ctl.len = 134;
1703 sc.len = sizeof (struct sockaddr_un) + 4;
1704 break;
1706 default:
1707 m_free(name);
1708 error = ENOSYS;
1709 goto out;
1711 m_free(name);
1713 dat.len = -1;
1714 fl = 0;
1715 st->s_cmd = SVR4_TI__ACCEPT_OK;
1716 break;
1718 case SVR4_TI_SENDTO_REQUEST:
1720 * XXX: dsl - I think this means that because we last did a
1721 * 'sendto' we'd better do a recvfrom now.
1723 DPRINTF(("getmsg: TI_SENDTO_REQUEST\n"));
1724 if (ctl.maxlen > 36 && ctl.len < 36)
1725 ctl.len = 36;
1726 if (ctl.len > sizeof(sc))
1727 ctl.len = sizeof(sc);
1729 if ((error = copyin(NETBSD32PTR(ctl.buf), &sc, ctl.len)) != 0)
1730 goto out;
1732 msg.msg_name = NULL;
1733 msg.msg_namelen = 0;
1734 msg.msg_iov = &aiov;
1735 msg.msg_iovlen = 1;
1736 msg.msg_control = 0;
1737 aiov.iov_base = NETBSD32PTR(dat.buf);
1738 aiov.iov_len = dat.maxlen;
1739 msg.msg_flags = 0;
1741 error = do_sys_recvmsg(l, SCARG(uap, fd), &msg, &name, NULL,
1742 retval);
1744 if (error) {
1745 DPRINTF(("getmsg: do_sys_recvmsg failed %d\n", error));
1746 goto out;
1749 sc.cmd = SVR4_TI_RECVFROM_IND;
1751 switch (st->s_family) {
1752 case AF_INET:
1753 sc.len = sizeof (struct sockaddr_in);
1754 sockaddr_to_netaddr_in(&sc, mtod(name, void *));
1755 break;
1757 case AF_LOCAL:
1758 sc.len = sizeof (struct sockaddr_un) + 4;
1759 sockaddr_to_netaddr_un(&sc, mtod(name, void *));
1760 break;
1762 default:
1763 m_free(name);
1764 error = ENOSYS;
1765 goto out;
1767 m_free(name);
1769 dat.len = *retval;
1770 fl = 0;
1771 st->s_cmd = sc.cmd;
1772 break;
1774 default:
1775 st->s_cmd = sc.cmd;
1776 #ifdef notyet
1777 if (st->s_cmd == SVR4_TI_CONNECT_REQUEST) {
1778 struct sys_read_args ra;
1780 /* More weirdness: Again, I can't find documentation
1781 * to back this up, but when a process does a generic
1782 * "getmsg()" call it seems that the command field is
1783 * zero and the length of the data area is zero. I
1784 * think processes expect getmsg() to fill in dat.len
1785 * after reading at most dat.maxlen octets from the
1786 * stream. Since we're using sockets I can let
1787 * read() look after it and frob return values
1788 * appropriately (or inappropriately :-)
1789 * -- newton@atdot.dotat.org XXX
1791 SCARG(&ra, fd) = SCARG(uap, fd);
1792 SCARG(&ra, buf) = dat.buf;
1793 SCARG(&ra, nbyte) = dat.maxlen;
1794 if ((error = sys_read(p, &ra, retval)) != 0)
1795 goto out;
1796 dat.len = *retval;
1797 *retval = 0;
1798 st->s_cmd = SVR4_TI_SENDTO_REQUEST;
1799 break;
1802 #endif
1803 DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd));
1804 error = EINVAL;
1805 goto out;
1808 if (SCARG_PTR(uap, ctl)) {
1809 if (ctl.len != -1)
1810 if ((error = copyout(&sc, NETBSD32PTR(ctl.buf),
1811 ctl.len)) != 0)
1812 goto out;
1814 if ((error = copyout(&ctl, SCARG_PTR(uap, ctl),
1815 sizeof(ctl))) != 0)
1816 goto out;
1819 if (SCARG_PTR(uap, dat)) {
1820 if ((error = copyout(&dat, SCARG_PTR(uap, dat),
1821 sizeof(dat))) != 0)
1822 goto out;
1825 if (SCARG_PTR(uap, flags)) { /* XXX: Need translation */
1826 if ((error = copyout(&fl, SCARG_PTR(uap, flags),
1827 sizeof(fl))) != 0)
1828 goto out;
1831 *retval = 0;
1833 #ifdef DEBUG_SVR4
1834 show_msg("<getmsg", SCARG(uap, fd), SCARG(uap, ctl),
1835 SCARG(uap, dat), fl);
1836 #endif /* DEBUG_SVR4 */
1838 out:
1839 fd_putfile(SCARG(uap, fd));
1840 return error;