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