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