svr4_stream.c revision 89308
1/*
2 * Copyright (c) 1998 Mark Newton.  All rights reserved.
3 * Copyright (c) 1994, 1996 Christos Zoulas.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by Christos Zoulas.
16 * 4. The name of the author may not be used to endorse or promote products
17 *    derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $FreeBSD: head/sys/compat/svr4/svr4_stream.c 89308 2002-01-13 12:07:15Z alfred $
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#define COMPAT_43 1
41
42#include <sys/param.h>
43#include <sys/systm.h>
44#include <sys/fcntl.h>
45#include <sys/filedesc.h>
46#include <sys/filio.h>
47#include <sys/lock.h>
48#include <sys/malloc.h>
49#include <sys/file.h> 		/* Must come after sys/malloc.h */
50#include <sys/mbuf.h>
51#include <sys/mutex.h>
52#include <sys/proc.h>
53#include <sys/protosw.h>
54#include <sys/signal.h>
55#include <sys/signalvar.h>
56#include <sys/socket.h>
57#include <sys/socketvar.h>
58#include <sys/stat.h>
59#include <sys/sysproto.h>
60#include <sys/uio.h>
61#include <sys/ktrace.h>		/* Must come after sys/uio.h */
62#include <sys/un.h>
63
64#include <netinet/in.h>
65
66#include <compat/svr4/svr4.h>
67#include <compat/svr4/svr4_types.h>
68#include <compat/svr4/svr4_util.h>
69#include <compat/svr4/svr4_signal.h>
70#include <compat/svr4/svr4_proto.h>
71#include <compat/svr4/svr4_stropts.h>
72#include <compat/svr4/svr4_timod.h>
73#include <compat/svr4/svr4_sockmod.h>
74#include <compat/svr4/svr4_ioctl.h>
75#include <compat/svr4/svr4_socket.h>
76
77/* Utils */
78static int clean_pipe __P((struct thread *, const char *));
79static void getparm __P((struct file *, struct svr4_si_sockparms *));
80static int svr4_do_putmsg __P((struct thread *, struct svr4_sys_putmsg_args *,
81			       struct file *));
82static int svr4_do_getmsg __P((struct thread *, struct svr4_sys_getmsg_args *,
83			       struct file *));
84
85/* Address Conversions */
86static void sockaddr_to_netaddr_in __P((struct svr4_strmcmd *,
87					const struct sockaddr_in *));
88static void sockaddr_to_netaddr_un __P((struct svr4_strmcmd *,
89					const struct sockaddr_un *));
90static void netaddr_to_sockaddr_in __P((struct sockaddr_in *,
91					const struct svr4_strmcmd *));
92static void netaddr_to_sockaddr_un __P((struct sockaddr_un *,
93					const struct svr4_strmcmd *));
94
95/* stream ioctls */
96static int i_nread __P((struct file *, struct thread *, register_t *, int,
97			u_long, caddr_t));
98static int i_fdinsert __P((struct file *, struct thread *, register_t *, int,
99			   u_long, caddr_t));
100static int i_str   __P((struct file *, struct thread *, register_t *, int,
101			u_long, caddr_t));
102static int i_setsig   __P((struct file *, struct thread *, register_t *, int,
103			u_long, caddr_t));
104static int i_getsig   __P((struct file *, struct thread *, register_t *, int,
105			u_long, caddr_t));
106static int _i_bind_rsvd __P((struct file *, struct thread *, register_t *, int,
107			     u_long, caddr_t));
108static int _i_rele_rsvd __P((struct file *, struct thread *, register_t *, int,
109			     u_long, caddr_t));
110
111/* i_str sockmod calls */
112static int sockmod       __P((struct file *, int, struct svr4_strioctl *,
113			      struct thread *));
114static int si_listen     __P((struct file *, int, struct svr4_strioctl *,
115			      struct thread *));
116static int si_ogetudata  __P((struct file *, int, struct svr4_strioctl *,
117			      struct thread *));
118static int si_sockparams __P((struct file *, int, struct svr4_strioctl *,
119			      struct thread *));
120static int si_shutdown	 __P((struct file *, int, struct svr4_strioctl *,
121			      struct thread *));
122static int si_getudata   __P((struct file *, int, struct svr4_strioctl *,
123			      struct thread *));
124
125/* i_str timod calls */
126static int timod         __P((struct file *, int, struct svr4_strioctl *,
127		              struct thread *));
128static int ti_getinfo    __P((struct file *, int, struct svr4_strioctl *,
129			      struct thread *));
130static int ti_bind       __P((struct file *, int, struct svr4_strioctl *,
131			      struct thread *));
132
133/* infrastructure */
134static int svr4_sendit __P((struct thread *td, int s, struct msghdr *mp,
135			    int flags));
136
137static int svr4_recvit __P((struct thread *td, int s, struct msghdr *mp,
138			    caddr_t namelenp));
139
140/* <sigh>  Ok, so we shouldn't use sendit() in uipc_syscalls.c because
141 * it isn't part of a "public" interface;  We're supposed to use
142 * pru_sosend instead.  Same goes for recvit()/pru_soreceive() for
143 * that matter.  Solution:  Suck sendit()/recvit() into here where we
144 * can do what we like.
145 *
146 * I hate code duplication.
147 *
148 * I will take out all the #ifdef COMPAT_OLDSOCK gumph, though.
149 */
150static int
151svr4_sendit(td, s, mp, flags)
152	register struct thread *td;
153	int s;
154	register struct msghdr *mp;
155	int flags;
156{
157	struct uio auio;
158	register struct iovec *iov;
159	register int i;
160	struct mbuf *control;
161	struct sockaddr *to;
162	int len, error;
163	struct socket *so;
164#ifdef KTRACE
165	struct iovec *ktriov = NULL;
166	struct uio ktruio;
167#endif
168
169	if ((error = fgetsock(td, s, &so, NULL)) != 0)
170		return (error);
171	auio.uio_iov = mp->msg_iov;
172	auio.uio_iovcnt = mp->msg_iovlen;
173	auio.uio_segflg = UIO_USERSPACE;
174	auio.uio_rw = UIO_WRITE;
175	auio.uio_td = td;
176	auio.uio_offset = 0;			/* XXX */
177	auio.uio_resid = 0;
178	iov = mp->msg_iov;
179	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
180		if ((auio.uio_resid += iov->iov_len) < 0) {
181			error = EINVAL;
182			goto done1;
183		}
184	}
185	if (mp->msg_name) {
186		error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
187		if (error)
188			goto done1;
189	} else {
190		to = 0;
191	}
192	if (mp->msg_control) {
193		if (mp->msg_controllen < sizeof(struct cmsghdr)) {
194			error = EINVAL;
195			goto bad;
196		}
197		error = sockargs(&control, mp->msg_control,
198		    mp->msg_controllen, MT_CONTROL);
199		if (error)
200			goto bad;
201	} else {
202		control = 0;
203	}
204#ifdef KTRACE
205	if (KTRPOINT(td->td_proc, KTR_GENIO)) {
206		int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
207
208		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
209		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
210		ktruio = auio;
211	}
212#endif
213	len = auio.uio_resid;
214	error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control,
215						     flags, td);
216	if (error) {
217		if (auio.uio_resid != len && (error == ERESTART ||
218		    error == EINTR || error == EWOULDBLOCK))
219			error = 0;
220		if (error == EPIPE) {
221			PROC_LOCK(td->td_proc);
222			psignal(td->td_proc, SIGPIPE);
223			PROC_UNLOCK(td->td_proc);
224		}
225	}
226	if (error == 0)
227		td->td_retval[0] = len - auio.uio_resid;
228#ifdef KTRACE
229	if (ktriov != NULL) {
230		if (error == 0) {
231			ktruio.uio_iov = ktriov;
232			ktruio.uio_resid = td->td_retval[0];
233			ktrgenio(td->td_proc->p_tracep, s, UIO_WRITE, &ktruio, error);
234		}
235		FREE(ktriov, M_TEMP);
236	}
237#endif
238bad:
239	if (to)
240		FREE(to, M_SONAME);
241done1:
242	fdrop(fp, td);
243	fputsock(so);
244	return (error);
245}
246
247static int
248svr4_recvit(td, s, mp, namelenp)
249	register struct thread *td;
250	int s;
251	register struct msghdr *mp;
252	caddr_t namelenp;
253{
254	struct uio auio;
255	register struct iovec *iov;
256	register int i;
257	int len, error;
258	struct mbuf *m, *control = 0;
259	caddr_t ctlbuf;
260	struct socket *so;
261	struct sockaddr *fromsa = 0;
262#ifdef KTRACE
263	struct iovec *ktriov = NULL;
264	struct uio ktruio;
265#endif
266
267	if ((error = fgetsock(td, s, &so, NULL)) != 0)
268		return (error);
269	auio.uio_iov = mp->msg_iov;
270	auio.uio_iovcnt = mp->msg_iovlen;
271	auio.uio_segflg = UIO_USERSPACE;
272	auio.uio_rw = UIO_READ;
273	auio.uio_td = td;
274	auio.uio_offset = 0;			/* XXX */
275	auio.uio_resid = 0;
276	iov = mp->msg_iov;
277	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
278		if ((auio.uio_resid += iov->iov_len) < 0) {
279			error = EINVAL;
280			goto done1;
281		}
282	}
283#ifdef KTRACE
284	if (KTRPOINT(td->td_proc, KTR_GENIO)) {
285		int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
286
287		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
288		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
289		ktruio = auio;
290	}
291#endif
292	len = auio.uio_resid;
293	error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio,
294	    (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
295	    &mp->msg_flags);
296	if (error) {
297		if (auio.uio_resid != len && (error == ERESTART ||
298		    error == EINTR || error == EWOULDBLOCK))
299			error = 0;
300	}
301#ifdef KTRACE
302	if (ktriov != NULL) {
303		if (error == 0) {
304			ktruio.uio_iov = ktriov;
305			ktruio.uio_resid = len - auio.uio_resid;
306			ktrgenio(td->td_proc->p_tracep, s, UIO_READ, &ktruio, error);
307		}
308		FREE(ktriov, M_TEMP);
309	}
310#endif
311	if (error)
312		goto out;
313	td->td_retval[0] = len - auio.uio_resid;
314	if (mp->msg_name) {
315		len = mp->msg_namelen;
316		if (len <= 0 || fromsa == 0)
317			len = 0;
318		else {
319#ifndef MIN
320#define MIN(a,b) ((a)>(b)?(b):(a))
321#endif
322			/* save sa_len before it is destroyed by MSG_COMPAT */
323			len = MIN(len, fromsa->sa_len);
324			error = copyout(fromsa,
325			    (caddr_t)mp->msg_name, (unsigned)len);
326			if (error)
327				goto out;
328		}
329		mp->msg_namelen = len;
330		if (namelenp &&
331		    (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) {
332			goto out;
333		}
334	}
335	if (mp->msg_control) {
336		len = mp->msg_controllen;
337		m = control;
338		mp->msg_controllen = 0;
339		ctlbuf = (caddr_t) mp->msg_control;
340
341		while (m && len > 0) {
342			unsigned int tocopy;
343
344			if (len >= m->m_len)
345				tocopy = m->m_len;
346			else {
347				mp->msg_flags |= MSG_CTRUNC;
348				tocopy = len;
349			}
350
351			if ((error = copyout((caddr_t)mtod(m, caddr_t),
352					ctlbuf, tocopy)) != 0)
353				goto out;
354
355			ctlbuf += tocopy;
356			len -= tocopy;
357			m = m->m_next;
358		}
359		mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control;
360	}
361out:
362	if (fromsa)
363		FREE(fromsa, M_SONAME);
364	if (control)
365		m_freem(control);
366done1:
367	fdrop(fp, td);
368	fputsock(so);
369	return (error);
370}
371
372#ifdef DEBUG_SVR4
373static void bufprint __P((u_char *, size_t));
374static int show_ioc __P((const char *, struct svr4_strioctl *));
375static int show_strbuf __P((struct svr4_strbuf *));
376static void show_msg __P((const char *, int, struct svr4_strbuf *,
377			  struct svr4_strbuf *, int));
378
379static void
380bufprint(buf, len)
381	u_char *buf;
382	size_t len;
383{
384	size_t i;
385
386	uprintf("\n\t");
387	for (i = 0; i < len; i++) {
388		uprintf("%x ", buf[i]);
389		if (i && (i % 16) == 0)
390			uprintf("\n\t");
391	}
392}
393
394static int
395show_ioc(str, ioc)
396	const char		*str;
397	struct svr4_strioctl	*ioc;
398{
399	u_char *ptr = (u_char *) malloc(ioc->len, M_TEMP, M_WAITOK);
400	int error;
401
402	uprintf("%s cmd = %ld, timeout = %d, len = %d, buf = %p { ",
403	    str, ioc->cmd, ioc->timeout, ioc->len, ioc->buf);
404
405	if ((error = copyin(ioc->buf, ptr, ioc->len)) != 0) {
406		free((char *) ptr, M_TEMP);
407		return error;
408	}
409
410	bufprint(ptr, ioc->len);
411
412	uprintf("}\n");
413
414	free((char *) ptr, M_TEMP);
415	return 0;
416}
417
418
419static int
420show_strbuf(str)
421	struct svr4_strbuf *str;
422{
423	int error;
424	u_char *ptr = NULL;
425	int maxlen = str->maxlen;
426	int len = str->len;
427
428	if (maxlen < 0)
429		maxlen = 0;
430
431	if (len >= maxlen)
432		len = maxlen;
433
434	if (len > 0) {
435	    ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK);
436
437	    if ((error = copyin(str->buf, ptr, len)) != 0) {
438		    free((char *) ptr, M_TEMP);
439		    return error;
440	    }
441	}
442
443	uprintf(", { %d, %d, %p=[ ", str->maxlen, str->len, str->buf);
444
445	if (ptr)
446		bufprint(ptr, len);
447
448	uprintf("]}");
449
450	if (ptr)
451		free((char *) ptr, M_TEMP);
452
453	return 0;
454}
455
456
457static void
458show_msg(str, fd, ctl, dat, flags)
459	const char		*str;
460	int			 fd;
461	struct svr4_strbuf	*ctl;
462	struct svr4_strbuf	*dat;
463	int			 flags;
464{
465	struct svr4_strbuf	buf;
466	int error;
467
468	uprintf("%s(%d", str, fd);
469	if (ctl != NULL) {
470		if ((error = copyin(ctl, &buf, sizeof(buf))) != 0)
471			return;
472		show_strbuf(&buf);
473	}
474	else
475		uprintf(", NULL");
476
477	if (dat != NULL) {
478		if ((error = copyin(dat, &buf, sizeof(buf))) != 0)
479			return;
480		show_strbuf(&buf);
481	}
482	else
483		uprintf(", NULL");
484
485	uprintf(", %x);\n", flags);
486}
487
488#endif /* DEBUG_SVR4 */
489
490/*
491 * We are faced with an interesting situation. On svr4 unix sockets
492 * are really pipes. But we really have sockets, and we might as
493 * well use them. At the point where svr4 calls TI_BIND, it has
494 * already created a named pipe for the socket using mknod(2).
495 * We need to create a socket with the same name when we bind,
496 * so we need to remove the pipe before, otherwise we'll get address
497 * already in use. So we *carefully* remove the pipe, to avoid
498 * using this as a random file removal tool. We use system calls
499 * to avoid code duplication.
500 */
501static int
502clean_pipe(td, path)
503	struct thread *td;
504	const char *path;
505{
506	struct lstat_args la;
507	struct unlink_args ua;
508	struct stat st;
509	int error;
510	caddr_t sg = stackgap_init();
511	size_t l = strlen(path) + 1;
512	void *tpath;
513
514	tpath = stackgap_alloc(&sg, l);
515	SCARG(&la, ub) = stackgap_alloc(&sg, sizeof(struct stat));
516
517	if ((error = copyout(path, tpath, l)) != 0)
518		return error;
519
520	SCARG(&la, path) = tpath;
521
522	if ((error = lstat(td, &la)) != 0)
523		return 0;
524
525	if ((error = copyin(SCARG(&la, ub), &st, sizeof(st))) != 0)
526		return 0;
527
528	/*
529	 * Make sure we are dealing with a mode 0 named pipe.
530	 */
531	if ((st.st_mode & S_IFMT) != S_IFIFO)
532		return 0;
533
534	if ((st.st_mode & ALLPERMS) != 0)
535		return 0;
536
537	SCARG(&ua, path) = SCARG(&la, path);
538
539	if ((error = unlink(td, &ua)) != 0) {
540		DPRINTF(("clean_pipe: unlink failed %d\n", error));
541		return error;
542	}
543
544	return 0;
545}
546
547
548static void
549sockaddr_to_netaddr_in(sc, sain)
550	struct svr4_strmcmd *sc;
551	const struct sockaddr_in *sain;
552{
553	struct svr4_netaddr_in *na;
554	na = SVR4_ADDROF(sc);
555
556	na->family = sain->sin_family;
557	na->port = sain->sin_port;
558	na->addr = sain->sin_addr.s_addr;
559	DPRINTF(("sockaddr_in -> netaddr %d %d %lx\n", na->family, na->port,
560		 na->addr));
561}
562
563
564static void
565sockaddr_to_netaddr_un(sc, saun)
566	struct svr4_strmcmd *sc;
567	const struct sockaddr_un *saun;
568{
569	struct svr4_netaddr_un *na;
570	char *dst, *edst = ((char *) sc) + sc->offs + sizeof(na->family) + 1  -
571	    sizeof(*sc);
572	const char *src;
573
574	na = SVR4_ADDROF(sc);
575	na->family = saun->sun_family;
576	for (src = saun->sun_path, dst = na->path; (*dst++ = *src++) != '\0'; )
577		if (dst == edst)
578			break;
579	DPRINTF(("sockaddr_un -> netaddr %d %s\n", na->family, na->path));
580}
581
582
583static void
584netaddr_to_sockaddr_in(sain, sc)
585	struct sockaddr_in *sain;
586	const struct svr4_strmcmd *sc;
587{
588	const struct svr4_netaddr_in *na;
589
590
591	na = SVR4_C_ADDROF(sc);
592	memset(sain, 0, sizeof(*sain));
593	sain->sin_len = sizeof(*sain);
594	sain->sin_family = na->family;
595	sain->sin_port = na->port;
596	sain->sin_addr.s_addr = na->addr;
597	DPRINTF(("netaddr -> sockaddr_in %d %d %x\n", sain->sin_family,
598		 sain->sin_port, sain->sin_addr.s_addr));
599}
600
601
602static void
603netaddr_to_sockaddr_un(saun, sc)
604	struct sockaddr_un *saun;
605	const struct svr4_strmcmd *sc;
606{
607	const struct svr4_netaddr_un *na;
608	char *dst, *edst = &saun->sun_path[sizeof(saun->sun_path) - 1];
609	const char *src;
610
611	na = SVR4_C_ADDROF(sc);
612	memset(saun, 0, sizeof(*saun));
613	saun->sun_family = na->family;
614	for (src = na->path, dst = saun->sun_path; (*dst++ = *src++) != '\0'; )
615		if (dst == edst)
616			break;
617	saun->sun_len = dst - saun->sun_path;
618	DPRINTF(("netaddr -> sockaddr_un %d %s\n", saun->sun_family,
619		 saun->sun_path));
620}
621
622
623static void
624getparm(fp, pa)
625	struct file *fp;
626	struct svr4_si_sockparms *pa;
627{
628	struct svr4_strm *st;
629	struct socket *so;
630
631	st = svr4_stream_get(fp);
632	if (st == NULL)
633		return;
634
635	so = (struct socket *) fp->f_data;
636
637	pa->family = st->s_family;
638
639	switch (so->so_type) {
640	case SOCK_DGRAM:
641		pa->type = SVR4_T_CLTS;
642		pa->protocol = IPPROTO_UDP;
643		DPRINTF(("getparm(dgram)\n"));
644		return;
645
646	case SOCK_STREAM:
647	        pa->type = SVR4_T_COTS;  /* What about T_COTS_ORD? XXX */
648		pa->protocol = IPPROTO_IP;
649		DPRINTF(("getparm(stream)\n"));
650		return;
651
652	case SOCK_RAW:
653		pa->type = SVR4_T_CLTS;
654		pa->protocol = IPPROTO_RAW;
655		DPRINTF(("getparm(raw)\n"));
656		return;
657
658	default:
659		pa->type = 0;
660		pa->protocol = 0;
661		DPRINTF(("getparm(type %d?)\n", so->so_type));
662		return;
663	}
664}
665
666
667static int
668si_ogetudata(fp, fd, ioc, td)
669	struct file		*fp;
670	int 			 fd;
671	struct svr4_strioctl	*ioc;
672	struct thread		*td;
673{
674	int error;
675	struct svr4_si_oudata ud;
676	struct svr4_si_sockparms pa;
677
678	if (ioc->len != sizeof(ud) && ioc->len != sizeof(ud) - sizeof(int)) {
679		DPRINTF(("SI_OGETUDATA: Wrong size %d != %d\n",
680			 sizeof(ud), ioc->len));
681		return EINVAL;
682	}
683
684	if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
685		return error;
686
687	getparm(fp, &pa);
688
689	switch (pa.family) {
690	case AF_INET:
691	    ud.tidusize = 16384;
692	    ud.addrsize = sizeof(struct svr4_sockaddr_in);
693	    if (pa.type == SVR4_SOCK_STREAM)
694		    ud.etsdusize = 1;
695	    else
696		    ud.etsdusize = 0;
697	    break;
698
699	case AF_LOCAL:
700	    ud.tidusize = 65536;
701	    ud.addrsize = 128;
702	    ud.etsdusize = 128;
703	    break;
704
705	default:
706	    DPRINTF(("SI_OGETUDATA: Unsupported address family %d\n",
707		     pa.family));
708	    return ENOSYS;
709	}
710
711	/* I have no idea what these should be! */
712	ud.optsize = 128;
713	ud.tsdusize = 128;
714
715	ud.servtype = pa.type;
716
717	/* XXX: Fixme */
718	ud.so_state = 0;
719	ud.so_options = 0;
720	return copyout(&ud, ioc->buf, ioc->len);
721}
722
723
724static int
725si_sockparams(fp, fd, ioc, td)
726	struct file		*fp;
727	int 			 fd;
728	struct svr4_strioctl	*ioc;
729	struct thread		*td;
730{
731	struct svr4_si_sockparms pa;
732
733	getparm(fp, &pa);
734	return copyout(&pa, ioc->buf, sizeof(pa));
735}
736
737
738static int
739si_listen(fp, fd, ioc, td)
740	struct file		*fp;
741	int 			 fd;
742	struct svr4_strioctl	*ioc;
743	struct thread		*td;
744{
745	int error;
746	struct svr4_strm *st = svr4_stream_get(fp);
747	struct svr4_strmcmd lst;
748	struct listen_args la;
749
750	if (st == NULL)
751		return EINVAL;
752
753	if ((error = copyin(ioc->buf, &lst, ioc->len)) != 0)
754		return error;
755
756	if (lst.cmd != SVR4_TI_OLD_BIND_REQUEST) {
757		DPRINTF(("si_listen: bad request %ld\n", lst.cmd));
758		return EINVAL;
759	}
760
761	/*
762	 * We are making assumptions again...
763	 */
764	SCARG(&la, s) = fd;
765	DPRINTF(("SI_LISTEN: fileno %d backlog = %d\n", fd, 5));
766	SCARG(&la, backlog) = 5;
767
768	if ((error = listen(td, &la)) != 0) {
769		DPRINTF(("SI_LISTEN: listen failed %d\n", error));
770		return error;
771	}
772
773	st->s_cmd = SVR4_TI__ACCEPT_WAIT;
774	lst.cmd = SVR4_TI_BIND_REPLY;
775
776	switch (st->s_family) {
777	case AF_INET:
778		/* XXX: Fill the length here */
779		break;
780
781	case AF_LOCAL:
782		lst.len = 140;
783		lst.pad[28] = 0x00000000;	/* magic again */
784		lst.pad[29] = 0x00000800;	/* magic again */
785		lst.pad[30] = 0x80001400;	/* magic again */
786		break;
787
788	default:
789		DPRINTF(("SI_LISTEN: Unsupported address family %d\n",
790		    st->s_family));
791		return ENOSYS;
792	}
793
794
795	if ((error = copyout(&lst, ioc->buf, ioc->len)) != 0)
796		return error;
797
798	return 0;
799}
800
801
802static int
803si_getudata(fp, fd, ioc, td)
804	struct file		*fp;
805	int 			 fd;
806	struct svr4_strioctl	*ioc;
807	struct thread		*td;
808{
809	int error;
810	struct svr4_si_udata ud;
811
812	if (sizeof(ud) != ioc->len) {
813		DPRINTF(("SI_GETUDATA: Wrong size %d != %d\n",
814			 sizeof(ud), ioc->len));
815		return EINVAL;
816	}
817
818	if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
819		return error;
820
821	getparm(fp, &ud.sockparms);
822
823	switch (ud.sockparms.family) {
824	case AF_INET:
825	    DPRINTF(("getudata_inet\n"));
826	    ud.tidusize = 16384;
827	    ud.tsdusize = 16384;
828	    ud.addrsize = sizeof(struct svr4_sockaddr_in);
829	    if (ud.sockparms.type == SVR4_SOCK_STREAM)
830		    ud.etsdusize = 1;
831	    else
832		    ud.etsdusize = 0;
833	    ud.optsize = 0;
834	    break;
835
836	case AF_LOCAL:
837	    DPRINTF(("getudata_local\n"));
838	    ud.tidusize = 65536;
839	    ud.tsdusize = 128;
840	    ud.addrsize = 128;
841	    ud.etsdusize = 128;
842	    ud.optsize = 128;
843	    break;
844
845	default:
846	    DPRINTF(("SI_GETUDATA: Unsupported address family %d\n",
847		     ud.sockparms.family));
848	    return ENOSYS;
849	}
850
851
852	ud.servtype = ud.sockparms.type;
853	DPRINTF(("ud.servtype = %d\n", ud.servtype));
854	/* XXX: Fixme */
855	ud.so_state = 0;
856	ud.so_options = 0;
857	return copyout(&ud, ioc->buf, sizeof(ud));
858}
859
860
861static int
862si_shutdown(fp, fd, ioc, td)
863	struct file		*fp;
864	int 			 fd;
865	struct svr4_strioctl	*ioc;
866	struct thread		*td;
867{
868	int error;
869	struct shutdown_args ap;
870
871	if (ioc->len != sizeof(SCARG(&ap, how))) {
872		DPRINTF(("SI_SHUTDOWN: Wrong size %d != %d\n",
873			 sizeof(SCARG(&ap, how)), ioc->len));
874		return EINVAL;
875	}
876
877	if ((error = copyin(ioc->buf, &SCARG(&ap, how), ioc->len)) != 0)
878		return error;
879
880	SCARG(&ap, s) = fd;
881
882	return shutdown(td, &ap);
883}
884
885
886static int
887sockmod(fp, fd, ioc, td)
888	struct file		*fp;
889	int			 fd;
890	struct svr4_strioctl	*ioc;
891	struct thread		*td;
892{
893	switch (ioc->cmd) {
894	case SVR4_SI_OGETUDATA:
895		DPRINTF(("SI_OGETUDATA\n"));
896		return si_ogetudata(fp, fd, ioc, td);
897
898	case SVR4_SI_SHUTDOWN:
899		DPRINTF(("SI_SHUTDOWN\n"));
900		return si_shutdown(fp, fd, ioc, td);
901
902	case SVR4_SI_LISTEN:
903		DPRINTF(("SI_LISTEN\n"));
904		return si_listen(fp, fd, ioc, td);
905
906	case SVR4_SI_SETMYNAME:
907		DPRINTF(("SI_SETMYNAME\n"));
908		return 0;
909
910	case SVR4_SI_SETPEERNAME:
911		DPRINTF(("SI_SETPEERNAME\n"));
912		return 0;
913
914	case SVR4_SI_GETINTRANSIT:
915		DPRINTF(("SI_GETINTRANSIT\n"));
916		return 0;
917
918	case SVR4_SI_TCL_LINK:
919		DPRINTF(("SI_TCL_LINK\n"));
920		return 0;
921
922	case SVR4_SI_TCL_UNLINK:
923		DPRINTF(("SI_TCL_UNLINK\n"));
924		return 0;
925
926	case SVR4_SI_SOCKPARAMS:
927		DPRINTF(("SI_SOCKPARAMS\n"));
928		return si_sockparams(fp, fd, ioc, td);
929
930	case SVR4_SI_GETUDATA:
931		DPRINTF(("SI_GETUDATA\n"));
932		return si_getudata(fp, fd, ioc, td);
933
934	default:
935		DPRINTF(("Unknown sockmod ioctl %lx\n", ioc->cmd));
936		return 0;
937
938	}
939}
940
941
942static int
943ti_getinfo(fp, fd, ioc, td)
944	struct file		*fp;
945	int 			 fd;
946	struct svr4_strioctl	*ioc;
947	struct thread		*td;
948{
949	int error;
950	struct svr4_infocmd info;
951
952	memset(&info, 0, sizeof(info));
953
954	if ((error = copyin(ioc->buf, &info, ioc->len)) != 0)
955		return error;
956
957	if (info.cmd != SVR4_TI_INFO_REQUEST)
958		return EINVAL;
959
960	info.cmd = SVR4_TI_INFO_REPLY;
961	info.tsdu = 0;
962	info.etsdu = 1;
963	info.cdata = -2;
964	info.ddata = -2;
965	info.addr = 16;
966	info.opt = -1;
967	info.tidu = 16384;
968	info.serv = 2;
969	info.current = 0;
970	info.provider = 2;
971
972	ioc->len = sizeof(info);
973	if ((error = copyout(&info, ioc->buf, ioc->len)) != 0)
974		return error;
975
976	return 0;
977}
978
979
980static int
981ti_bind(fp, fd, ioc, td)
982	struct file		*fp;
983	int 			 fd;
984	struct svr4_strioctl	*ioc;
985	struct thread		*td;
986{
987	int error;
988	struct svr4_strm *st = svr4_stream_get(fp);
989	struct sockaddr_in sain;
990	struct sockaddr_un saun;
991	caddr_t sg;
992	void *skp, *sup = NULL;
993	int sasize;
994	struct svr4_strmcmd bnd;
995	struct bind_args ba;
996
997	if (st == NULL) {
998		DPRINTF(("ti_bind: bad file descriptor\n"));
999		return EINVAL;
1000	}
1001
1002	if ((error = copyin(ioc->buf, &bnd, ioc->len)) != 0)
1003		return error;
1004
1005	if (bnd.cmd != SVR4_TI_OLD_BIND_REQUEST) {
1006		DPRINTF(("ti_bind: bad request %ld\n", bnd.cmd));
1007		return EINVAL;
1008	}
1009
1010	switch (st->s_family) {
1011	case AF_INET:
1012		skp = &sain;
1013		sasize = sizeof(sain);
1014
1015		if (bnd.offs == 0)
1016			goto reply;
1017
1018		netaddr_to_sockaddr_in(&sain, &bnd);
1019
1020		DPRINTF(("TI_BIND: fam %d, port %d, addr %x\n",
1021			 sain.sin_family, sain.sin_port,
1022			 sain.sin_addr.s_addr));
1023		break;
1024
1025	case AF_LOCAL:
1026		skp = &saun;
1027		sasize = sizeof(saun);
1028		if (bnd.offs == 0)
1029			goto reply;
1030
1031		netaddr_to_sockaddr_un(&saun, &bnd);
1032
1033		if (saun.sun_path[0] == '\0')
1034			goto reply;
1035
1036		DPRINTF(("TI_BIND: fam %d, path %s\n",
1037			 saun.sun_family, saun.sun_path));
1038
1039		if ((error = clean_pipe(td, saun.sun_path)) != 0)
1040			return error;
1041
1042		bnd.pad[28] = 0x00001000;	/* magic again */
1043		break;
1044
1045	default:
1046		DPRINTF(("TI_BIND: Unsupported address family %d\n",
1047			 st->s_family));
1048		return ENOSYS;
1049	}
1050
1051	sg = stackgap_init();
1052	sup = stackgap_alloc(&sg, sasize);
1053
1054	if ((error = copyout(skp, sup, sasize)) != 0)
1055		return error;
1056
1057	SCARG(&ba, s) = fd;
1058	DPRINTF(("TI_BIND: fileno %d\n", fd));
1059	SCARG(&ba, name) = (void *) sup;
1060	SCARG(&ba, namelen) = sasize;
1061
1062	if ((error = bind(td, &ba)) != 0) {
1063		DPRINTF(("TI_BIND: bind failed %d\n", error));
1064		return error;
1065	}
1066
1067reply:
1068	if (sup == NULL) {
1069		memset(&bnd, 0, sizeof(bnd));
1070		bnd.len = sasize + 4;
1071		bnd.offs = 0x10;	/* XXX */
1072	}
1073
1074	bnd.cmd = SVR4_TI_BIND_REPLY;
1075
1076	if ((error = copyout(&bnd, ioc->buf, ioc->len)) != 0)
1077		return error;
1078
1079	return 0;
1080}
1081
1082
1083static int
1084timod(fp, fd, ioc, td)
1085	struct file		*fp;
1086	int			 fd;
1087	struct svr4_strioctl	*ioc;
1088	struct thread		*td;
1089{
1090	switch (ioc->cmd) {
1091	case SVR4_TI_GETINFO:
1092		DPRINTF(("TI_GETINFO\n"));
1093		return ti_getinfo(fp, fd, ioc, td);
1094
1095	case SVR4_TI_OPTMGMT:
1096		DPRINTF(("TI_OPTMGMT\n"));
1097		return 0;
1098
1099	case SVR4_TI_BIND:
1100		DPRINTF(("TI_BIND\n"));
1101		return ti_bind(fp, fd, ioc, td);
1102
1103	case SVR4_TI_UNBIND:
1104		DPRINTF(("TI_UNBIND\n"));
1105		return 0;
1106
1107	default:
1108		DPRINTF(("Unknown timod ioctl %lx\n", ioc->cmd));
1109		return 0;
1110	}
1111}
1112
1113
1114int
1115svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
1116	struct file *fp;
1117	struct thread *td;
1118	register_t *retval;
1119	int fd;
1120	u_long cmd;
1121	caddr_t dat;
1122{
1123	struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat;
1124	struct svr4_strm *st = svr4_stream_get(fp);
1125	int error;
1126	void *skp, *sup;
1127	struct sockaddr_in sain;
1128	struct sockaddr_un saun;
1129	struct svr4_strmcmd sc;
1130	int sasize;
1131	caddr_t sg;
1132	int *lenp;
1133
1134	DPRINTF(("svr4_stream_ti_ioctl\n"));
1135
1136	if (st == NULL)
1137		return EINVAL;
1138
1139	sc.offs = 0x10;
1140
1141	if ((error = copyin(sub, &skb, sizeof(skb))) != 0) {
1142		DPRINTF(("ti_ioctl: error copying in strbuf\n"));
1143		return error;
1144	}
1145
1146	switch (st->s_family) {
1147	case AF_INET:
1148		skp = &sain;
1149		sasize = sizeof(sain);
1150		break;
1151
1152	case AF_LOCAL:
1153		skp = &saun;
1154		sasize = sizeof(saun);
1155		break;
1156
1157	default:
1158		DPRINTF(("ti_ioctl: Unsupported address family %d\n",
1159			 st->s_family));
1160		return ENOSYS;
1161	}
1162
1163	sg = stackgap_init();
1164	sup = stackgap_alloc(&sg, sasize);
1165	lenp = stackgap_alloc(&sg, sizeof(*lenp));
1166
1167	if ((error = copyout(&sasize, lenp, sizeof(*lenp))) != 0) {
1168		DPRINTF(("ti_ioctl: error copying out lenp\n"));
1169		return error;
1170	}
1171
1172	switch (cmd) {
1173	case SVR4_TI_GETMYNAME:
1174		DPRINTF(("TI_GETMYNAME\n"));
1175		{
1176			struct getsockname_args ap;
1177			SCARG(&ap, fdes) = fd;
1178			SCARG(&ap, asa) = sup;
1179			SCARG(&ap, alen) = lenp;
1180			if ((error = getsockname(td, &ap)) != 0) {
1181				DPRINTF(("ti_ioctl: getsockname error\n"));
1182				return error;
1183			}
1184		}
1185		break;
1186
1187	case SVR4_TI_GETPEERNAME:
1188		DPRINTF(("TI_GETPEERNAME\n"));
1189		{
1190			struct getpeername_args ap;
1191			SCARG(&ap, fdes) = fd;
1192			SCARG(&ap, asa) = sup;
1193			SCARG(&ap, alen) = lenp;
1194			if ((error = getpeername(td, &ap)) != 0) {
1195				DPRINTF(("ti_ioctl: getpeername error\n"));
1196				return error;
1197			}
1198		}
1199		break;
1200
1201	case SVR4_TI_SETMYNAME:
1202		DPRINTF(("TI_SETMYNAME\n"));
1203		return 0;
1204
1205	case SVR4_TI_SETPEERNAME:
1206		DPRINTF(("TI_SETPEERNAME\n"));
1207		return 0;
1208	default:
1209		DPRINTF(("ti_ioctl: Unknown ioctl %lx\n", cmd));
1210		return ENOSYS;
1211	}
1212
1213	if ((error = copyin(sup, skp, sasize)) != 0) {
1214		DPRINTF(("ti_ioctl: error copying in socket data\n"));
1215		return error;
1216	}
1217
1218	if ((error = copyin(lenp, &sasize, sizeof(*lenp))) != 0) {
1219		DPRINTF(("ti_ioctl: error copying in socket size\n"));
1220		return error;
1221	}
1222
1223	switch (st->s_family) {
1224	case AF_INET:
1225		sockaddr_to_netaddr_in(&sc, &sain);
1226		skb.len = sasize;
1227		break;
1228
1229	case AF_LOCAL:
1230		sockaddr_to_netaddr_un(&sc, &saun);
1231		skb.len = sasize + 4;
1232		break;
1233
1234	default:
1235		return ENOSYS;
1236	}
1237
1238
1239	if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) {
1240		DPRINTF(("ti_ioctl: error copying out socket data\n"));
1241		return error;
1242	}
1243
1244
1245	if ((error = copyout(&skb, sub, sizeof(skb))) != 0) {
1246		DPRINTF(("ti_ioctl: error copying out strbuf\n"));
1247		return error;
1248	}
1249
1250	return error;
1251}
1252
1253
1254
1255
1256static int
1257i_nread(fp, td, retval, fd, cmd, dat)
1258	struct file *fp;
1259	struct thread *td;
1260	register_t *retval;
1261	int fd;
1262	u_long cmd;
1263	caddr_t dat;
1264{
1265	int error;
1266	int nread = 0;
1267
1268	/*
1269	 * We are supposed to return the message length in nread, and the
1270	 * number of messages in retval. We don't have the notion of number
1271	 * of stream messages, so we just find out if we have any bytes waiting
1272	 * for us, and if we do, then we assume that we have at least one
1273	 * message waiting for us.
1274	 */
1275	if ((error = fo_ioctl(fp, FIONREAD, (caddr_t) &nread, td)) != 0)
1276		return error;
1277
1278	if (nread != 0)
1279		*retval = 1;
1280	else
1281		*retval = 0;
1282
1283	return copyout(&nread, dat, sizeof(nread));
1284}
1285
1286static int
1287i_fdinsert(fp, td, retval, fd, cmd, dat)
1288	struct file *fp;
1289	struct thread *td;
1290	register_t *retval;
1291	int fd;
1292	u_long cmd;
1293	caddr_t dat;
1294{
1295	/*
1296	 * Major hack again here. We assume that we are using this to
1297	 * implement accept(2). If that is the case, we have already
1298	 * called accept, and we have stored the file descriptor in
1299	 * afd. We find the file descriptor that the code wants to use
1300	 * in fd insert, and then we dup2() our accepted file descriptor
1301	 * to it.
1302	 */
1303	int error;
1304	struct svr4_strm *st = svr4_stream_get(fp);
1305	struct svr4_strfdinsert fdi;
1306	struct dup2_args d2p;
1307	struct close_args clp;
1308
1309	if (st == NULL) {
1310		DPRINTF(("fdinsert: bad file type\n"));
1311		return EINVAL;
1312	}
1313
1314	if (st->s_afd == -1) {
1315		DPRINTF(("fdinsert: accept fd not found\n"));
1316		return ENOENT;
1317	}
1318
1319	if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) {
1320		DPRINTF(("fdinsert: copyin failed %d\n", error));
1321		return error;
1322	}
1323
1324	SCARG(&d2p, from) = st->s_afd;
1325	SCARG(&d2p, to) = fdi.fd;
1326
1327	if ((error = dup2(td, &d2p)) != 0) {
1328		DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n",
1329		    st->s_afd, fdi.fd, error));
1330		return error;
1331	}
1332
1333	SCARG(&clp, fd) = st->s_afd;
1334
1335	if ((error = close(td, &clp)) != 0) {
1336		DPRINTF(("fdinsert: close(%d) failed %d\n",
1337		    st->s_afd, error));
1338		return error;
1339	}
1340
1341	st->s_afd = -1;
1342
1343	*retval = 0;
1344	return 0;
1345}
1346
1347
1348static int
1349_i_bind_rsvd(fp, td, retval, fd, cmd, dat)
1350	struct file *fp;
1351	struct thread *td;
1352	register_t *retval;
1353	int fd;
1354	u_long cmd;
1355	caddr_t dat;
1356{
1357	struct mkfifo_args ap;
1358
1359	/*
1360	 * This is a supposed to be a kernel and library only ioctl.
1361	 * It gets called before ti_bind, when we have a unix
1362	 * socket, to physically create the socket transport and
1363	 * ``reserve'' it. I don't know how this get reserved inside
1364	 * the kernel, but we are going to create it nevertheless.
1365	 */
1366	SCARG(&ap, path) = dat;
1367	SCARG(&ap, mode) = S_IFIFO;
1368
1369	return mkfifo(td, &ap);
1370}
1371
1372static int
1373_i_rele_rsvd(fp, td, retval, fd, cmd, dat)
1374	struct file *fp;
1375	struct thread *td;
1376	register_t *retval;
1377	int fd;
1378	u_long cmd;
1379	caddr_t dat;
1380{
1381	struct unlink_args ap;
1382
1383	/*
1384	 * This is a supposed to be a kernel and library only ioctl.
1385	 * I guess it is supposed to release the socket.
1386	 */
1387	SCARG(&ap, path) = dat;
1388
1389	return unlink(td, &ap);
1390}
1391
1392static int
1393i_str(fp, td, retval, fd, cmd, dat)
1394	struct file *fp;
1395	struct thread *td;
1396	register_t *retval;
1397	int fd;
1398	u_long cmd;
1399	caddr_t dat;
1400{
1401	int			 error;
1402	struct svr4_strioctl	 ioc;
1403
1404	if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0)
1405		return error;
1406
1407#ifdef DEBUG_SVR4
1408	if ((error = show_ioc(">", &ioc)) != 0)
1409		return error;
1410#endif /* DEBUG_SVR4 */
1411
1412	switch (ioc.cmd & 0xff00) {
1413	case SVR4_SIMOD:
1414		if ((error = sockmod(fp, fd, &ioc, td)) != 0)
1415			return error;
1416		break;
1417
1418	case SVR4_TIMOD:
1419		if ((error = timod(fp, fd, &ioc, td)) != 0)
1420			return error;
1421		break;
1422
1423	default:
1424		DPRINTF(("Unimplemented module %c %ld\n",
1425			 (char) (cmd >> 8), cmd & 0xff));
1426		return 0;
1427	}
1428
1429#ifdef DEBUG_SVR4
1430	if ((error = show_ioc("<", &ioc)) != 0)
1431		return error;
1432#endif /* DEBUG_SVR4 */
1433	return copyout(&ioc, dat, sizeof(ioc));
1434}
1435
1436static int
1437i_setsig(fp, td, retval, fd, cmd, dat)
1438	struct file *fp;
1439	struct thread *td;
1440	register_t *retval;
1441	int fd;
1442	u_long cmd;
1443	caddr_t dat;
1444{
1445	/*
1446	 * This is the best we can do for now; we cannot generate
1447	 * signals only for specific events so the signal mask gets
1448	 * ignored; we save it just to pass it to a possible I_GETSIG...
1449	 *
1450	 * We alse have to fix the O_ASYNC fcntl bit, so the
1451	 * process will get SIGPOLLs.
1452	 */
1453	struct fcntl_args fa;
1454	int error;
1455	register_t oflags, flags;
1456	struct svr4_strm *st = svr4_stream_get(fp);
1457
1458	if (st == NULL) {
1459		DPRINTF(("i_setsig: bad file descriptor\n"));
1460		return EINVAL;
1461	}
1462	/* get old status flags */
1463	SCARG(&fa, fd) = fd;
1464	SCARG(&fa, cmd) = F_GETFL;
1465	if ((error = fcntl(td, &fa)) != 0)
1466		return error;
1467
1468	oflags = td->td_retval[0];
1469
1470	/* update the flags */
1471	if (dat != NULL) {
1472		int mask;
1473
1474		flags = oflags | O_ASYNC;
1475		if ((error = copyin(dat, &mask, sizeof(mask))) != 0) {
1476			  DPRINTF(("i_setsig: bad eventmask pointer\n"));
1477			  return error;
1478		}
1479		if (mask & SVR4_S_ALLMASK) {
1480			  DPRINTF(("i_setsig: bad eventmask data %x\n", mask));
1481			  return EINVAL;
1482		}
1483		st->s_eventmask = mask;
1484	}
1485	else {
1486		flags = oflags & ~O_ASYNC;
1487		st->s_eventmask = 0;
1488	}
1489
1490	/* set the new flags, if changed */
1491	if (flags != oflags) {
1492		SCARG(&fa, cmd) = F_SETFL;
1493		SCARG(&fa, arg) = (long) flags;
1494		if ((error = fcntl(td, &fa)) != 0)
1495			  return error;
1496		flags = td->td_retval[0];
1497	}
1498
1499	/* set up SIGIO receiver if needed */
1500	if (dat != NULL) {
1501		SCARG(&fa, cmd) = F_SETOWN;
1502		SCARG(&fa, arg) = (long) td->td_proc->p_pid;
1503		return fcntl(td, &fa);
1504	}
1505	return 0;
1506}
1507
1508static int
1509i_getsig(fp, td, retval, fd, cmd, dat)
1510	struct file *fp;
1511	struct thread *td;
1512	register_t *retval;
1513	int fd;
1514	u_long cmd;
1515	caddr_t dat;
1516{
1517	int error;
1518
1519	if (dat != NULL) {
1520		struct svr4_strm *st = svr4_stream_get(fp);
1521
1522		if (st == NULL) {
1523			DPRINTF(("i_getsig: bad file descriptor\n"));
1524			return EINVAL;
1525		}
1526		if ((error = copyout(&st->s_eventmask, dat,
1527				     sizeof(st->s_eventmask))) != 0) {
1528			DPRINTF(("i_getsig: bad eventmask pointer\n"));
1529			return error;
1530		}
1531	}
1532	return 0;
1533}
1534
1535int
1536svr4_stream_ioctl(fp, td, retval, fd, cmd, dat)
1537	struct file *fp;
1538	struct thread *td;
1539	register_t *retval;
1540	int fd;
1541	u_long cmd;
1542	caddr_t dat;
1543{
1544	*retval = 0;
1545
1546	/*
1547	 * All the following stuff assumes "sockmod" is pushed...
1548	 */
1549	switch (cmd) {
1550	case SVR4_I_NREAD:
1551		DPRINTF(("I_NREAD\n"));
1552		return i_nread(fp, td, retval, fd, cmd, dat);
1553
1554	case SVR4_I_PUSH:
1555		DPRINTF(("I_PUSH %p\n", dat));
1556#if defined(DEBUG_SVR4)
1557		show_strbuf((struct svr4_strbuf *)dat);
1558#endif
1559		return 0;
1560
1561	case SVR4_I_POP:
1562		DPRINTF(("I_POP\n"));
1563		return 0;
1564
1565	case SVR4_I_LOOK:
1566		DPRINTF(("I_LOOK\n"));
1567		return 0;
1568
1569	case SVR4_I_FLUSH:
1570		DPRINTF(("I_FLUSH\n"));
1571		return 0;
1572
1573	case SVR4_I_SRDOPT:
1574		DPRINTF(("I_SRDOPT\n"));
1575		return 0;
1576
1577	case SVR4_I_GRDOPT:
1578		DPRINTF(("I_GRDOPT\n"));
1579		return 0;
1580
1581	case SVR4_I_STR:
1582		DPRINTF(("I_STR\n"));
1583		return i_str(fp, td, retval, fd, cmd, dat);
1584
1585	case SVR4_I_SETSIG:
1586		DPRINTF(("I_SETSIG\n"));
1587		return i_setsig(fp, td, retval, fd, cmd, dat);
1588
1589	case SVR4_I_GETSIG:
1590	        DPRINTF(("I_GETSIG\n"));
1591		return i_getsig(fp, td, retval, fd, cmd, dat);
1592
1593	case SVR4_I_FIND:
1594		DPRINTF(("I_FIND\n"));
1595		/*
1596		 * Here we are not pushing modules really, we just
1597		 * pretend all are present
1598		 */
1599		*retval = 0;
1600		return 0;
1601
1602	case SVR4_I_LINK:
1603		DPRINTF(("I_LINK\n"));
1604		return 0;
1605
1606	case SVR4_I_UNLINK:
1607		DPRINTF(("I_UNLINK\n"));
1608		return 0;
1609
1610	case SVR4_I_ERECVFD:
1611		DPRINTF(("I_ERECVFD\n"));
1612		return 0;
1613
1614	case SVR4_I_PEEK:
1615		DPRINTF(("I_PEEK\n"));
1616		return 0;
1617
1618	case SVR4_I_FDINSERT:
1619		DPRINTF(("I_FDINSERT\n"));
1620		return i_fdinsert(fp, td, retval, fd, cmd, dat);
1621
1622	case SVR4_I_SENDFD:
1623		DPRINTF(("I_SENDFD\n"));
1624		return 0;
1625
1626	case SVR4_I_RECVFD:
1627		DPRINTF(("I_RECVFD\n"));
1628		return 0;
1629
1630	case SVR4_I_SWROPT:
1631		DPRINTF(("I_SWROPT\n"));
1632		return 0;
1633
1634	case SVR4_I_GWROPT:
1635		DPRINTF(("I_GWROPT\n"));
1636		return 0;
1637
1638	case SVR4_I_LIST:
1639		DPRINTF(("I_LIST\n"));
1640		return 0;
1641
1642	case SVR4_I_PLINK:
1643		DPRINTF(("I_PLINK\n"));
1644		return 0;
1645
1646	case SVR4_I_PUNLINK:
1647		DPRINTF(("I_PUNLINK\n"));
1648		return 0;
1649
1650	case SVR4_I_SETEV:
1651		DPRINTF(("I_SETEV\n"));
1652		return 0;
1653
1654	case SVR4_I_GETEV:
1655		DPRINTF(("I_GETEV\n"));
1656		return 0;
1657
1658	case SVR4_I_STREV:
1659		DPRINTF(("I_STREV\n"));
1660		return 0;
1661
1662	case SVR4_I_UNSTREV:
1663		DPRINTF(("I_UNSTREV\n"));
1664		return 0;
1665
1666	case SVR4_I_FLUSHBAND:
1667		DPRINTF(("I_FLUSHBAND\n"));
1668		return 0;
1669
1670	case SVR4_I_CKBAND:
1671		DPRINTF(("I_CKBAND\n"));
1672		return 0;
1673
1674	case SVR4_I_GETBAND:
1675		DPRINTF(("I_GETBANK\n"));
1676		return 0;
1677
1678	case SVR4_I_ATMARK:
1679		DPRINTF(("I_ATMARK\n"));
1680		return 0;
1681
1682	case SVR4_I_SETCLTIME:
1683		DPRINTF(("I_SETCLTIME\n"));
1684		return 0;
1685
1686	case SVR4_I_GETCLTIME:
1687		DPRINTF(("I_GETCLTIME\n"));
1688		return 0;
1689
1690	case SVR4_I_CANPUT:
1691		DPRINTF(("I_CANPUT\n"));
1692		return 0;
1693
1694	case SVR4__I_BIND_RSVD:
1695		DPRINTF(("_I_BIND_RSVD\n"));
1696		return _i_bind_rsvd(fp, td, retval, fd, cmd, dat);
1697
1698	case SVR4__I_RELE_RSVD:
1699		DPRINTF(("_I_RELE_RSVD\n"));
1700		return _i_rele_rsvd(fp, td, retval, fd, cmd, dat);
1701
1702	default:
1703		DPRINTF(("unimpl cmd = %lx\n", cmd));
1704		break;
1705	}
1706
1707	return 0;
1708}
1709
1710
1711
1712int
1713svr4_sys_putmsg(td, uap)
1714	register struct thread *td;
1715	struct svr4_sys_putmsg_args *uap;
1716{
1717	struct file     *fp;
1718	int error;
1719
1720	fp = ffind_hold(td, uap->fd);
1721	if (fp == NULL) {
1722#ifdef DEBUG_SVR4
1723	        uprintf("putmsg: bad fp\n");
1724#endif
1725		return EBADF;
1726	}
1727	error = svr4_do_putmsg(td, uap, fp);
1728	fdrop(fp, td);
1729	return (error);
1730}
1731
1732static int
1733svr4_do_putmsg(td, uap, fp)
1734	struct thread *td;
1735	struct svr4_sys_putmsg_args *uap;
1736	struct file	*fp;
1737{
1738	struct svr4_strbuf dat, ctl;
1739	struct svr4_strmcmd sc;
1740	struct sockaddr_in sain;
1741	struct sockaddr_un saun;
1742	void *skp, *sup;
1743	int sasize, *retval;
1744	struct svr4_strm *st;
1745	int error;
1746	caddr_t sg;
1747
1748	retval = td->td_retval;
1749
1750#ifdef DEBUG_SVR4
1751	show_msg(">putmsg", SCARG(uap, fd), SCARG(uap, ctl),
1752		 SCARG(uap, dat), SCARG(uap, flags));
1753#endif /* DEBUG_SVR4 */
1754
1755	FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
1756
1757	if (SCARG(uap, ctl) != NULL) {
1758	  if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0) {
1759#ifdef DEBUG_SVR4
1760	    uprintf("putmsg: copyin(): %d\n", error);
1761#endif
1762	    return error;
1763	  }
1764	}
1765	else
1766		ctl.len = -1;
1767
1768	if (SCARG(uap, dat) != NULL) {
1769	  if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0) {
1770#ifdef DEBUG_SVR4
1771	    uprintf("putmsg: copyin(): %d (2)\n", error);
1772#endif
1773	    return error;
1774	  }
1775	}
1776	else
1777		dat.len = -1;
1778
1779	/*
1780	 * Only for sockets for now.
1781	 */
1782	if ((st = svr4_stream_get(fp)) == NULL) {
1783		DPRINTF(("putmsg: bad file type\n"));
1784		return EINVAL;
1785	}
1786
1787	if (ctl.len > sizeof(sc)) {
1788		DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len,
1789			 sizeof(struct svr4_strmcmd)));
1790		return EINVAL;
1791	}
1792
1793	if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
1794		return error;
1795
1796	switch (st->s_family) {
1797	case AF_INET:
1798	        if (sc.len != sizeof(sain)) {
1799		        if (sc.cmd == SVR4_TI_DATA_REQUEST) {
1800			        struct write_args wa;
1801
1802				/* Solaris seems to use sc.cmd = 3 to
1803				 * send "expedited" data.  telnet uses
1804				 * this for options processing, sending EOF,
1805				 * etc.  I'm sure other things use it too.
1806				 * I don't have any documentation
1807				 * on it, so I'm making a guess that this
1808				 * is how it works. newton@atdot.dotat.org XXX
1809				 */
1810				DPRINTF(("sending expedited data ??\n"));
1811				SCARG(&wa, fd) = SCARG(uap, fd);
1812				SCARG(&wa, buf) = dat.buf;
1813				SCARG(&wa, nbyte) = dat.len;
1814				return write(td, &wa);
1815			}
1816	                DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len));
1817	                return EINVAL;
1818	        }
1819	        netaddr_to_sockaddr_in(&sain, &sc);
1820	        skp = &sain;
1821	        sasize = sizeof(sain);
1822	        error = sain.sin_family != st->s_family;
1823		break;
1824
1825	case AF_LOCAL:
1826		if (ctl.len == 8) {
1827			/* We are doing an accept; succeed */
1828			DPRINTF(("putmsg: Do nothing\n"));
1829			*retval = 0;
1830			return 0;
1831		}
1832		else {
1833			/* Maybe we've been given a device/inode pair */
1834			udev_t *dev = SVR4_ADDROF(&sc);
1835			ino_t *ino = (ino_t *) &dev[1];
1836			skp = svr4_find_socket(td, fp, *dev, *ino);
1837			if (skp == NULL) {
1838				skp = &saun;
1839				/* I guess we have it by name */
1840				netaddr_to_sockaddr_un(skp, &sc);
1841			}
1842			sasize = sizeof(saun);
1843		}
1844		break;
1845
1846	default:
1847		DPRINTF(("putmsg: Unsupported address family %d\n",
1848			 st->s_family));
1849		return ENOSYS;
1850	}
1851
1852	sg = stackgap_init();
1853	sup = stackgap_alloc(&sg, sasize);
1854
1855	if ((error = copyout(skp, sup, sasize)) != 0)
1856		return error;
1857
1858	switch (st->s_cmd = sc.cmd) {
1859	case SVR4_TI_CONNECT_REQUEST:	/* connect 	*/
1860		{
1861			struct connect_args co;
1862
1863			SCARG(&co, s) = SCARG(uap, fd);
1864			SCARG(&co, name) = (void *) sup;
1865			SCARG(&co, namelen) = (int) sasize;
1866
1867			return connect(td, &co);
1868		}
1869
1870	case SVR4_TI_SENDTO_REQUEST:	/* sendto 	*/
1871		{
1872			struct msghdr msg;
1873			struct iovec aiov;
1874
1875			msg.msg_name = (caddr_t) sup;
1876			msg.msg_namelen = sasize;
1877			msg.msg_iov = &aiov;
1878			msg.msg_iovlen = 1;
1879			msg.msg_control = 0;
1880			msg.msg_flags = 0;
1881			aiov.iov_base = dat.buf;
1882			aiov.iov_len = dat.len;
1883#if 0
1884			error = so->so_proto->pr_usrreqs->pru_sosend(so, 0,
1885					      uio, 0, 0, 0, uio->uio_td);
1886#endif
1887			error = svr4_sendit(td, SCARG(uap, fd), &msg,
1888				       SCARG(uap, flags));
1889			DPRINTF(("sendto_request error: %d\n", error));
1890			*retval = 0;
1891			return error;
1892		}
1893
1894	default:
1895		DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd));
1896		return ENOSYS;
1897	}
1898}
1899
1900int
1901svr4_sys_getmsg(td, uap)
1902	struct thread *td;
1903	struct svr4_sys_getmsg_args *uap;
1904{
1905	struct file     *fp;
1906	int error;
1907
1908	fp = ffind_hold(td, uap->fd);
1909	if (fp == NULL) {
1910#ifdef DEBUG_SVR4
1911	        uprintf("getmsg: bad fp\n");
1912#endif
1913		return EBADF;
1914	}
1915	error = svr4_do_getmsg(td, uap, fp);
1916	fdrop(fp, td);
1917	return (error);
1918}
1919
1920int
1921svr4_sys_getmsg(td, uap)
1922	register struct thread *td;
1923	struct svr4_sys_getmsg_args *uap;
1924	struct file *fp;
1925{
1926	struct getpeername_args ga;
1927	struct accept_args aa;
1928	struct svr4_strbuf dat, ctl;
1929	struct svr4_strmcmd sc;
1930	int error, *retval;
1931	struct msghdr msg;
1932	struct iovec aiov;
1933	struct sockaddr_in sain;
1934	struct sockaddr_un saun;
1935	void *skp, *sup;
1936	int sasize;
1937	struct svr4_strm *st;
1938	int *flen;
1939	int fl;
1940	caddr_t sg;
1941
1942	retval = td->td_retval;
1943
1944	FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
1945
1946	memset(&sc, 0, sizeof(sc));
1947
1948#ifdef DEBUG_SVR4
1949	show_msg(">getmsg", SCARG(uap, fd), SCARG(uap, ctl),
1950		 SCARG(uap, dat), 0);
1951#endif /* DEBUG_SVR4 */
1952
1953	if (SCARG(uap, ctl) != NULL) {
1954		if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0)
1955			return error;
1956	}
1957	else {
1958		ctl.len = -1;
1959		ctl.maxlen = 0;
1960	}
1961
1962	if (SCARG(uap, dat) != NULL) {
1963	    	if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0)
1964			return error;
1965	}
1966	else {
1967		dat.len = -1;
1968		dat.maxlen = 0;
1969	}
1970
1971	/*
1972	 * Only for sockets for now.
1973	 */
1974	if ((st = svr4_stream_get(fp)) == NULL) {
1975		DPRINTF(("getmsg: bad file type\n"));
1976		return EINVAL;
1977	}
1978
1979	if (ctl.maxlen == -1 || dat.maxlen == -1) {
1980		DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n"));
1981		return ENOSYS;
1982	}
1983
1984	switch (st->s_family) {
1985	case AF_INET:
1986		skp = &sain;
1987		sasize = sizeof(sain);
1988		break;
1989
1990	case AF_LOCAL:
1991		skp = &saun;
1992		sasize = sizeof(saun);
1993		break;
1994
1995	default:
1996		DPRINTF(("getmsg: Unsupported address family %d\n",
1997			 st->s_family));
1998		return ENOSYS;
1999	}
2000
2001	sg = stackgap_init();
2002	sup = stackgap_alloc(&sg, sasize);
2003	flen = (int *) stackgap_alloc(&sg, sizeof(*flen));
2004
2005	fl = sasize;
2006	if ((error = copyout(&fl, flen, sizeof(fl))) != 0)
2007		return error;
2008
2009	switch (st->s_cmd) {
2010	case SVR4_TI_CONNECT_REQUEST:
2011		DPRINTF(("getmsg: TI_CONNECT_REQUEST\n"));
2012		/*
2013		 * We do the connect in one step, so the putmsg should
2014		 * have gotten the error.
2015		 */
2016		sc.cmd = SVR4_TI_OK_REPLY;
2017		sc.len = 0;
2018
2019		ctl.len = 8;
2020		dat.len = -1;
2021		fl = 1;
2022		st->s_cmd = sc.cmd;
2023		break;
2024
2025	case SVR4_TI_OK_REPLY:
2026		DPRINTF(("getmsg: TI_OK_REPLY\n"));
2027		/*
2028		 * We are immediately after a connect reply, so we send
2029		 * a connect verification.
2030		 */
2031
2032		SCARG(&ga, fdes) = SCARG(uap, fd);
2033		SCARG(&ga, asa) = (void *) sup;
2034		SCARG(&ga, alen) = flen;
2035
2036		if ((error = getpeername(td, &ga)) != 0) {
2037			DPRINTF(("getmsg: getpeername failed %d\n", error));
2038			return error;
2039		}
2040
2041		if ((error = copyin(sup, skp, sasize)) != 0)
2042			return error;
2043
2044		sc.cmd = SVR4_TI_CONNECT_REPLY;
2045		sc.pad[0] = 0x4;
2046		sc.offs = 0x18;
2047		sc.pad[1] = 0x14;
2048		sc.pad[2] = 0x04000402;
2049
2050		switch (st->s_family) {
2051		case AF_INET:
2052			sc.len = sasize;
2053			sockaddr_to_netaddr_in(&sc, &sain);
2054			break;
2055
2056		case AF_LOCAL:
2057			sc.len = sasize + 4;
2058			sockaddr_to_netaddr_un(&sc, &saun);
2059			break;
2060
2061		default:
2062			return ENOSYS;
2063		}
2064
2065		ctl.len = 40;
2066		dat.len = -1;
2067		fl = 0;
2068		st->s_cmd = sc.cmd;
2069		break;
2070
2071	case SVR4_TI__ACCEPT_OK:
2072		DPRINTF(("getmsg: TI__ACCEPT_OK\n"));
2073		/*
2074		 * We do the connect in one step, so the putmsg should
2075		 * have gotten the error.
2076		 */
2077		sc.cmd = SVR4_TI_OK_REPLY;
2078		sc.len = 1;
2079
2080		ctl.len = 8;
2081		dat.len = -1;
2082		fl = 1;
2083		st->s_cmd = SVR4_TI__ACCEPT_WAIT;
2084		break;
2085
2086	case SVR4_TI__ACCEPT_WAIT:
2087		DPRINTF(("getmsg: TI__ACCEPT_WAIT\n"));
2088		/*
2089		 * We are after a listen, so we try to accept...
2090		 */
2091		SCARG(&aa, s) = SCARG(uap, fd);
2092		SCARG(&aa, name) = (void *) sup;
2093		SCARG(&aa, anamelen) = flen;
2094
2095		if ((error = accept(td, &aa)) != 0) {
2096			DPRINTF(("getmsg: accept failed %d\n", error));
2097			return error;
2098		}
2099
2100		st->s_afd = *retval;
2101
2102		DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd));
2103
2104		if ((error = copyin(sup, skp, sasize)) != 0)
2105			return error;
2106
2107		sc.cmd = SVR4_TI_ACCEPT_REPLY;
2108		sc.offs = 0x18;
2109		sc.pad[0] = 0x0;
2110
2111		switch (st->s_family) {
2112		case AF_INET:
2113			sc.pad[1] = 0x28;
2114			sockaddr_to_netaddr_in(&sc, &sain);
2115			ctl.len = 40;
2116			sc.len = sasize;
2117			break;
2118
2119		case AF_LOCAL:
2120			sc.pad[1] = 0x00010000;
2121			sc.pad[2] = 0xf6bcdaa0;	/* I don't know what that is */
2122			sc.pad[3] = 0x00010000;
2123			ctl.len = 134;
2124			sc.len = sasize + 4;
2125			break;
2126
2127		default:
2128			return ENOSYS;
2129		}
2130
2131		dat.len = -1;
2132		fl = 0;
2133		st->s_cmd = SVR4_TI__ACCEPT_OK;
2134		break;
2135
2136	case SVR4_TI_SENDTO_REQUEST:
2137		DPRINTF(("getmsg: TI_SENDTO_REQUEST\n"));
2138		if (ctl.maxlen > 36 && ctl.len < 36)
2139		    ctl.len = 36;
2140
2141		if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
2142			return error;
2143
2144		switch (st->s_family) {
2145		case AF_INET:
2146			sockaddr_to_netaddr_in(&sc, &sain);
2147			break;
2148
2149		case AF_LOCAL:
2150			sockaddr_to_netaddr_un(&sc, &saun);
2151			break;
2152
2153		default:
2154			return ENOSYS;
2155		}
2156
2157		msg.msg_name = (caddr_t) sup;
2158		msg.msg_namelen = sasize;
2159		msg.msg_iov = &aiov;
2160		msg.msg_iovlen = 1;
2161		msg.msg_control = 0;
2162		aiov.iov_base = dat.buf;
2163		aiov.iov_len = dat.maxlen;
2164		msg.msg_flags = 0;
2165
2166		error = svr4_recvit(td, SCARG(uap, fd), &msg, (caddr_t) flen);
2167
2168		if (error) {
2169			DPRINTF(("getmsg: recvit failed %d\n", error));
2170			return error;
2171		}
2172
2173		if ((error = copyin(msg.msg_name, skp, sasize)) != 0)
2174			return error;
2175
2176		sc.cmd = SVR4_TI_RECVFROM_IND;
2177
2178		switch (st->s_family) {
2179		case AF_INET:
2180			sc.len = sasize;
2181			sockaddr_to_netaddr_in(&sc, &sain);
2182			break;
2183
2184		case AF_LOCAL:
2185			sc.len = sasize + 4;
2186			sockaddr_to_netaddr_un(&sc, &saun);
2187			break;
2188
2189		default:
2190			return ENOSYS;
2191		}
2192
2193		dat.len = *retval;
2194		fl = 0;
2195		st->s_cmd = sc.cmd;
2196		break;
2197
2198	default:
2199		st->s_cmd = sc.cmd;
2200		if (st->s_cmd == SVR4_TI_CONNECT_REQUEST) {
2201		        struct read_args ra;
2202
2203			/* More weirdness:  Again, I can't find documentation
2204			 * to back this up, but when a process does a generic
2205			 * "getmsg()" call it seems that the command field is
2206			 * zero and the length of the data area is zero.  I
2207			 * think processes expect getmsg() to fill in dat.len
2208			 * after reading at most dat.maxlen octets from the
2209			 * stream.  Since we're using sockets I can let
2210			 * read() look after it and frob return values
2211			 * appropriately (or inappropriately :-)
2212			 *   -- newton@atdot.dotat.org        XXX
2213			 */
2214			SCARG(&ra, fd) = SCARG(uap, fd);
2215			SCARG(&ra, buf) = dat.buf;
2216			SCARG(&ra, nbyte) = dat.maxlen;
2217			if ((error = read(td, &ra)) != 0) {
2218			        return error;
2219			}
2220			dat.len = *retval;
2221			*retval = 0;
2222			st->s_cmd = SVR4_TI_SENDTO_REQUEST;
2223			break;
2224		}
2225		DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd));
2226		return EINVAL;
2227	}
2228
2229	if (SCARG(uap, ctl)) {
2230		if (ctl.len != -1)
2231			if ((error = copyout(&sc, ctl.buf, ctl.len)) != 0)
2232				return error;
2233
2234		if ((error = copyout(&ctl, SCARG(uap, ctl), sizeof(ctl))) != 0)
2235			return error;
2236	}
2237
2238	if (SCARG(uap, dat)) {
2239		if ((error = copyout(&dat, SCARG(uap, dat), sizeof(dat))) != 0)
2240			return error;
2241	}
2242
2243	if (SCARG(uap, flags)) { /* XXX: Need translation */
2244		if ((error = copyout(&fl, SCARG(uap, flags), sizeof(fl))) != 0)
2245			return error;
2246	}
2247
2248	*retval = 0;
2249
2250#ifdef DEBUG_SVR4
2251	show_msg("<getmsg", SCARG(uap, fd), SCARG(uap, ctl),
2252		 SCARG(uap, dat), fl);
2253#endif /* DEBUG_SVR4 */
2254	return error;
2255}
2256
2257int svr4_sys_send(td, uap)
2258	struct thread *td;
2259	struct svr4_sys_send_args *uap;
2260{
2261	struct osend_args osa;
2262	SCARG(&osa, s) = SCARG(uap, s);
2263	SCARG(&osa, buf) = SCARG(uap, buf);
2264	SCARG(&osa, len) = SCARG(uap, len);
2265	SCARG(&osa, flags) = SCARG(uap, flags);
2266	return osend(td, &osa);
2267}
2268
2269int svr4_sys_recv(td, uap)
2270	struct thread *td;
2271	struct svr4_sys_recv_args *uap;
2272{
2273	struct orecv_args ora;
2274	SCARG(&ora, s) = SCARG(uap, s);
2275	SCARG(&ora, buf) = SCARG(uap, buf);
2276	SCARG(&ora, len) = SCARG(uap, len);
2277	SCARG(&ora, flags) = SCARG(uap, flags);
2278	return orecv(td, &ora);
2279}
2280
2281/*
2282 * XXX This isn't necessary, but it's handy for inserting debug code into
2283 * sendto().  Let's leave it here for now...
2284 */
2285int
2286svr4_sys_sendto(td, uap)
2287        struct thread *td;
2288        struct svr4_sys_sendto_args *uap;
2289{
2290        struct sendto_args sa;
2291
2292	SCARG(&sa, s) = SCARG(uap, s);
2293	SCARG(&sa, buf) = SCARG(uap, buf);
2294	SCARG(&sa, len) = SCARG(uap, len);
2295	SCARG(&sa, flags) = SCARG(uap, flags);
2296	SCARG(&sa, to) = (caddr_t)SCARG(uap, to);
2297	SCARG(&sa, tolen) = SCARG(uap, tolen);
2298
2299	DPRINTF(("calling sendto()\n"));
2300	return sendto(td, &sa);
2301}
2302
2303