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