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